文化与代码的交汇:OpenCC 驱动的中文语系兼容性解决方案

前言:openCC是什么?

OpenCC(Open Chinese Convert )是一个开源的中文简繁体转换工具,专为高质量、可控的中文转换而设计。它可以在不同中文地区(中国大陆、台湾、香港等)之间进行精确的字符和词汇转换。

🔧 核心特点

特性 说明
✅ 高质量转换 不只是字符替换,还支持词语级转换(考虑语境)
✅ 支持多种转换模式 简体 ↔ 繁体、简体 ↔ 台湾正体、简体 ↔ 香港繁体等
✅ 多平台支持 支持 C++、Node.js、Python、WebAssembly(浏览器)等
✅ 配置可定制 使用 JSON 格式的配置文件控制转换规则
✅ 开源免费 GitHub 开源,遵循 Apache 2.0 协议

🔄 支持的转换方向

配置文件 转换方向
s2t.json 简体 → 繁体(通用)
t2s.json 繁体 → 简体
s2tw.json 简体 → 台湾正体
tw2s.json 台湾正体 → 简体
s2hk.json 简体 → 香港繁体
hk2s.json 香港繁体 → 简体

📦 应用场景

  • 国际化网站(i18n)支持简繁切换
  • 中文文档统一标准格式
  • 电商、社交、新闻等跨区域中文内容发布
  • NLP/文本处理中的语言标准化预处理

在VUE2框架中实操

  1. 下载 opencc-js
js 复制代码
npm install opencc-js
  1. 创建language.js自定义方法
js 复制代码
// src/utils/language.js
import OpenCC from "opencc-js";

const changeLang = (lang = "cn") => {
  const converter = OpenCC.Converter({
    from: lang === "hk" ? "cn" : "hk",
    to: lang,
  });

  convertPageText(converter);
  localStorage.setItem("lang", lang);
};

const convertPageText = (converter) => {
  const walker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_TEXT,
    null,
    false
  );
  while (walker.nextNode()) {
    const node = walker.currentNode;
    node.nodeValue = converter(node.nodeValue);
  }
};

export default {
  changeLang,
  convertPageText,
};
  1. 将自定义的方法挂载到全局
js 复制代码
// src/main.js
// 引入自定义方法
import LanguageUtil from './utils/language';
// 挂在全局方法
Vue.prototype.$changeLang = LanguageUtil.changeLang;
Vue.prototype.$convertPageText = LanguageUtil.convertPageText;
  1. public/index.html 中引入 OpenCC(或者访问路径直接将文件内容保存到public下./引入)
js 复制代码
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/full.js">
  1. 自定义组件
html 复制代码
<template>
  <div class="lang-switch">
    <el-select
      v-model="currentLang"
      @change="changeLang"
      placeholder="请选择语言"
      size="mini"
      style="width: 120px"
    >
      <el-option label="中文简体" value="cn" />
      <el-option label="中文繁体" value="hk" />
    </el-select>
  </div>
</template>

<script>
export default {
  name: "LangSwitch",
  data() {
    return {
      // 拿到lang值,没有默认中文简体cn
      currentLang: localStorage.getItem("lang") || "cn",
    };
  },
  watch: {
    // 监听路由变化
    $route() {
      // 确保路由变化后dom渲染完成后执行语言切换
      this.$nextTick(() => {
        const lang = localStorage.getItem("lang") || "cn";
        const converter = OpenCC.Converter({
          from: lang === "hk" ? "cn" : "hk",
          to: lang,
        });
        this.convertPageText(converter);
        this.currentLang = lang;
        localStorage.setItem("lang", lang);
      });
    },
  },
  mounted() {
    // 组件加载后执行语言转换(如果不是默认简体)
    if (this.currentLang !== "cn") {
      this.changeLang(this.currentLang);
    }
  },
  methods: {
    changeLang(lang) {
      const converter = OpenCC.Converter({
        from: lang === "hk" ? "cn" : "hk",
        to: lang,
      });
      this.convertPageText(converter);
      this.currentLang = lang;
      localStorage.setItem("lang", lang);
      // 派发全局事件
      // 这里派发全局事件,因为element-ui的输入框、选择框、时间选择器等里带有placeholder的文字提示内容在document.body中获取不到,所以无法翻译,需要手动派发事件在输入框、选择框、时间选择器等所在的页面中手动触发调用翻译方法
      window.dispatchEvent(
        // 事件名称 langChanged
        new CustomEvent("langChanged")
      );
    },
    convertPageText(converter) {
      // 这里获取document.body来翻译
      const walker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_TEXT,
        null,
        false
      );
      while (walker.nextNode()) {
        const node = walker.currentNode;
        node.nodeValue = converter(node.nodeValue);
      }
    },
  },
};
</script>

<style scoped>
.lang-switch {
  padding: 10px;
}
</style>
  1. 每个页面中调用自定义方法来翻译
js 复制代码
// 在每个页面中watch中监听数据变化,数据变化时获取选择的语言值,更新语言
// 例如分页数据会变化,如果不再次调用翻译方法,分页后的数据翻译则失效
watch: {
    // 例如监听 listData,列表数据变化则翻译,防止页面切换翻译失效
    listData: {
      handler(newVal) {
        if (newVal && newVal.length > 0) {
          const lang = localStorage.getItem("lang") || "cn";
          this.$nextTick(() => {
            if (lang !== "cn") {
              // 直接调用全局已挂载的方法
              this.$changeLang(lang);
            }
          });
        }
      },
      immediate: true, // 初始化时也触发一次(如果需要)
      deep: true, // 深度监听,监听数组内部元素变化
    },
  },
  1. 解决placeholder内容在document.body中获取不到的问题
js 复制代码
<tempate>
    // 输入框、选择框、时间选择器等的所在页面
    // 例如是输入框
    <el-input
     v-model="searchData.file_name"
     :placeholder="fileNameText"
    ></el-input>
</template>
export default {
    name:"",
    data(){
        return {
            searchData: {
                file_name:"",
            },
            fileNameText:"", // 单独定义每个placeholder
        }
    }
    mounted() {
     // 这里触发派发的事件(事件名,事件执行函数)
     window.addEventListener("langChanged", this.onLangChanged);
     this.onPlaceholder();// 用来转换placeholder中的文字
    ];
  },
  beforeDestroy() {
    // 移除监听器,防止内存泄漏
    window.removeEventListener("langChanged", this.onLangChanged);
  },
  methods: {
    onLangChanged(e) {
      this.onPlaceholder();
    },

    async onPlaceholder() {
      this.fileNameText = await this.deepCopyAndConvert("请输入...");
    },
    // 深拷贝数据根据进行 简-繁或繁-简 的转换
    async deepCopyAndConvert(value) {
      const lang = localStorage.getItem("lang");
      if (value == null) return value;

      const copiedValue = JSON.parse(JSON.stringify(value));

      if (typeof copiedValue === "string") {
        let converter;
        if (lang !== "cn") {
          converter = await OpenCC.Converter({ from: "cn", to: "hk" });
        } else {
          converter = await OpenCC.Converter({ from: "hk", to: "cn" });
        }
        return converter(copiedValue);
      }
      return copiedValue;
    },
  }
}
相关推荐
阿奇__38 分钟前
element 跨页选中,回显el-table选中数据
前端·vue.js·elementui
努力往上爬de蜗牛39 分钟前
vue3 daterange正则踩坑
javascript·vue.js·elementui
谢尔登39 分钟前
【React】SWR 和 React Query(TanStack Query)
前端·react.js·前端框架
断竿散人39 分钟前
专题一、HTML5基础教程-Viewport属性深入理解:移动端网页的魔法钥匙
前端
3Katrina40 分钟前
理解Promise:让异步编程更优雅
前端·javascript
星之金币41 分钟前
关于我用Cursor优化了一篇文章:30 分钟学会定制属于你的编程语言
前端·javascript
天外来物43 分钟前
实战分享:用CI/CD实现持续部署
前端·nginx·docker
moxiaoran575344 分钟前
Spring Cloud Gateway 动态路由实现方案
运维·服务器·前端
市民中心的蟋蟀44 分钟前
第十一章 这三个全局状态管理库之间的共性与差异 【上】
前端·javascript·react.js
小宋102144 分钟前
el-table的select回显问题
javascript·vue.js·elementui