update vue插件和文档

This commit is contained in:
wxzhang 2023-01-24 22:00:31 +08:00
parent dfc3344359
commit 8575f319b8
9 changed files with 176 additions and 107 deletions

View File

@ -19,7 +19,7 @@ import { t } from "../../../languages"
为此,我们提供了插件可以来自动完成翻译函数的自动导入,包括: 为此,我们提供了插件可以来自动完成翻译函数的自动导入,包括:
- (Babel插件)[../tools/babel] - [Babel插件](../tools/babel)
- (Vite插件)[../tools/vite] - [Vite插件](../tools/vite)
当启用了`babel/vite`插件后,就会在编译时自动导入`t`函数。关于插件如何使用请参阅文档。 当启用了`babel/vite`插件后,就会在编译时自动导入`t`函数。关于插件如何使用请参阅文档。

View File

@ -1,9 +1,15 @@
# 更新日志 # 更新日志
## 2023/1/24
- `@voerkai18n/vite`默认不自动导入`t`函数
- 重构`@voerkai18n/vue`,详见`指南`介绍
- 新增`typescript``vue`例子
## 2023/1/11 ## 2023/1/11
- 重构`@voerkai18n/react`,支持自动重新渲染 - 重构`@voerkai18n/react`,支持自动重新渲染
- 修复`@voerkai18n/vite`插件在转码`jsx`组件时存在的idMap错误 - 修复`@voerkai18n/vite`插件在转码`jsx`组件时存在的`idMap`错误
## 2023/1/10 ## 2023/1/10

View File

@ -35,9 +35,28 @@ export default defineConfig({
## 插件功能 ## 插件功能
`@voerkai18n/vite`插件配置启用后,`vite`在进行`dev``build`时,就会在`<script setup>....</script>`自动注入`import { t } from "languages" `,同时会扫描源代码文件(包括`vue`,`js`等),根据`idMap.js`文件里面的文本映射表,将`t('"xxxx")`转换成`t("<id>")`的形式。 ### 文本映射
不同于`@voerkai18n/babel`插件,`@voerkai18n/vite`插件不需要配置`location``autoImport`参数,能正确地处理导入`languages`路径。 - `@voerkai18n/vite`插件配置启用后,同时会扫描源代码文件(包括`vue`,`js`等),根据`idMap.js`文件里面的文本映射表,将`t('"xxxx")`转换成`t("<id>")`的形式。
### 自动导入`t`函数
针对`js`文件,能通过指定`autoImport=true`来自动导入`t`函数。我们知道本质上翻译就是导入执行`t`函数,这样在一个复杂应用中可能就会存在这样的导入
```javascript | pure
import { t } from "languages"
import { t } from "../languages"
import { t } from "../../languages"
import { t } from "../../../languages"
import { t } from "../../languages"
```
`@voerkai18n/vite`插件可以实现自动导入功能,在`js`文件中不需要导入该函数,而是由`@voerkai18n/vite`插件在翻译阶段根据当前文件是否有使用了`t`函数而自动导入。
**注意:**
- 自动导入默认是关闭的,需要手动配置`@voerkai18n/vite`插件的参数`autoImport=true`才能生效。
- 对于使用`typescript`开发则不建议开启自动导入功能,因此这会导入类型的丢失。
- 不同于`@voerkai18n/babel`插件,`@voerkai18n/vite`插件不需要配置`location``autoImport`参数,能正确地处理导入`languages`路径。
## 插件参数 ## 插件参数
@ -50,7 +69,7 @@ export default defineConfig({
Inspect(), // 可选的 Inspect(), // 可选的
Voerkai18nPlugin({ Voerkai18nPlugin({
location: "./", // 可选的,指定当前工程目录 location: "./", // 可选的,指定当前工程目录
autoImport: true, // 是否自动导入t函数 autoImport: false, // 是否自动导入t函数
debug:false, // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单 debug:false, // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单
patterns:[ patterns:[
"!(?<!.vue\?.*).(css|json|scss|less|sass)$", // 排除所有css文件 "!(?<!.vue\?.*).(css|json|scss|less|sass)$", // 排除所有css文件
@ -64,7 +83,7 @@ export default defineConfig({
- `location`:可选的,用来指定当前工程目录,一般情况是不需要配置的,会自动取当前文件夹。并且假设`languages`文件夹在`<location>/src/languages`文件夹下。 - `location`:可选的,用来指定当前工程目录,一般情况是不需要配置的,会自动取当前文件夹。并且假设`languages`文件夹在`<location>/src/languages`文件夹下。
- `autoImport`:可选的,默认`true`,用来配置是否自动导入`t`函数。当vue文件没有指定导入时才会自动导入并且根据当前vue文件的路径处理好导入位置。 - `autoImport`:可选的,默认`false`,用来配置是否自动导入`t`函数。当vue文件没有指定导入时才会自动导入并且根据当前vue文件的路径处理好导入位置。
- `debug`:可选的,开启后会在控制台输出一些调试信息,对一般用户没有用。 - `debug`:可选的,开启后会在控制台输出一些调试信息,对一般用户没有用。

View File

@ -1,9 +1,6 @@
# Vue应用 # Vue应用
创建`Vue`应用一般采用`Vite``Vue Cli`来创建工程。在`Vue3`应用中引入`voerkai18n`来添加国际化应用需要由两个插件来简化应用。
创建`Vue`应用可以采用`Vite``Vue Cli`来创建工程。
`Vue3`应用中引入`voerkai18n`来添加国际化应用需要由两个插件来简化应用。
- **@voerkai18n/vue** - **@voerkai18n/vue**
@ -11,7 +8,7 @@
- **@voerkai18n/vite** - **@voerkai18n/vite**
**Vite插件**,在`vite.config.js`中配置,用来实现`自动文本映射``自动导入t函数`等功能。 **Vite插件**,在`vite.config.js`中配置,用来实现`自动文本映射`等功能。
`@voerkai18n/vue``@voerkai18n/vite`两件插件相互配合,安装配置好这两个插件后,就可以在`Vue`文件使用多语言`t`函数。 `@voerkai18n/vue``@voerkai18n/vite`两件插件相互配合,安装配置好这两个插件后,就可以在`Vue`文件使用多语言`t`函数。
@ -27,35 +24,71 @@
> voerka18n init > voerka18n init
// 提取要翻译的文本到src/languages/translates/*.json // 提取要翻译的文本到src/languages/translates/*.json
> voerkai18n extract > voerkai18n extract
// 进行人工翻译或自动翻译(百度) // 可选,进行人工翻译或自动翻译(百度)
> voerkai18n translate --apikey xxxx --apiid xxxxx > voerkai18n translate --apikey xxxx --apiid xxxxx
// 编译语言包 // 编译语言包
> voerkai18n compile > voerkai18n compile
``` ```
## 第二步:导入`t`翻译函数 ## 第二步:配置`@voerkai18n/vite`插件
无论采用何种工具创建`Vite`应用,均可以直接从`languages`直接导入`t`函数。
```vue `@voerkai18n/vite`插件可以根据`idMap.ts`映射文件将源码中的`t("xxxxx")`转换为`t("<数字>")`的形式,从而实现消除翻译内容的冗余内容。
<script setup>
import { t } from "./languages"
</script>
```
取决于您是从哪一个文件中导入,需要修改导入位置,可能类似这样:
```javascript | pure
import { t } from "./languages"
import { t } from "../languages"
import { t } from "../../languages"
import { t } from "../../../languages"
```
导入`t`函数后就可以直接使用了。 `@voerkai18n/vite`插件的安装非常简单,只需要在`vite.config.(ts|js)`中添加如下内容:
```javascript | pure ```javascript | pure
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Inspect from 'vite-plugin-inspect'
import Voerkai18nPlugin from "@voerkai18n/vite"
export default defineConfig({
plugins: [
Inspect(), // 可选
Voerkai18nPlugin(),
vue()],
})
```
`@voerkai18n/vite`插件仅在开发和构建阶段作用。事实上,如果不在乎文本内容的冗余,不安装此插件也是可以工作正常的。
## 第三步:配置`@voerkai18n/vue`插件
`@voerkai18n/vue`插件用来自动注入`t`函数、切换语言等功能。
安装方法如下:
```javascript pure
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 导入插件
import i18nPlugin from '@voerkai18n/vue'
// 导入当前作用域
import { i18nScope } from './languages'
const app = createApp(App)
// 应用插件
app.use(i18nPlugin,{i18nScope})
app.mount('#app')
```
`@voerkai18n/vue`插件本质上是为每一个Vue组件自动混入`t`函数。
## 第四步:使用`t`翻译函数
`Vue`应用使用多语言本质是调用`import { t } from 'langauges`导入的`t`函数来进行翻译。
```javascript | pure
// 在setup中需要手动导入t函数
<Script setup> <Script setup>
// 如果没有在vite.config.js中配置`@voerkai18n/vite`插件则需要手工导入t函数 import { t } from "./languages"
// import { t } from "./languages" console.log(t("Welcome to VoerkaI18n"))
</Script> </Script>
// 直接使用t函数不需要导入
<script> <script>
export default { export default {
data(){ data(){
@ -72,6 +105,7 @@ export default {
} }
} }
</script> </script>
// 直接使用
<template> <template>
<div> <div>
<h1>{{ t("请输入用户名称") }}</h1> <h1>{{ t("请输入用户名称") }}</h1>
@ -85,36 +119,28 @@ export default {
</template> </template>
``` ```
## 第三步:自动导入`t`翻译函数 **重点:**
- 在`<script setup>`中手动导入`import { t } from "./languages"`
当源码文件非常多时,手动导入`t`函数比较麻烦,我们提供了`vite``babel`两个插件可以实现自动导入`t`函数。 - 在`<script>``<template>`中可以直接使用`t`函数进行翻译。
如果应用是采用`Vite`+`@vitejs/plugin-vite`创建的工程,则可以通过配置`@voerkai18n/vite`插件实现自动导入`t`函数。 - `@voerkai18n/vue`插件本质上是为每一个Vue组件自动混入`t`函数,并在在语言切换时会自动重新渲染
详见`@voerkai18n/vite`插件介绍。
**重点:`t`函数会在使用`@voerkai18n/vite`插件后自动注入,因此在`Vue`文件中可以直接使用。** ## 第五步:切换语言
## 第四步:切换语言
引入`@voerkai18n/vue`插件来实现切换语言和自动重新渲染的功能。 引入`@voerkai18n/vue`插件来实现切换语言和自动重新渲染的功能。
```javascript | pure ```vue | pure
import { createApp } from 'vue'
import Root from './App.vue' <script setup lang="ts">
import i18nPlugin from '@voerkai18n/vue' import { injectVoerkaI18n } from "@voerkai18n/vue"
import { i18nScope } from './languages'
const app = createApp(Root) // 提供一个i18n对象
app.use(i18nPlugin,{ i18nScope }) // 重点需要引入i18nScope const i18n = injectVoerkaI18n()
app.mount('#app') </script>
```
`@voerkai18n/vue`插件安装后,提供了一个`i18n`实例,可以在组件中进行`inject`。就可以按如下方式使用:
```javascript | pure
<script> <script>
export default { export default {
inject: ['i18n'] // 此值由`@voerkai18n/vue`插件提供 //......
} }
</script> </script>
<template> <template>
@ -122,14 +148,20 @@ export default {
<h1>{{ t("中华人民共和国")}} </h1> <h1>{{ t("中华人民共和国")}} </h1>
<h2>{{ t("迎接中华民族的伟大复兴")}} </h2> <h2>{{ t("迎接中华民族的伟大复兴")}} </h2>
<h5>默认语言:{{ i18n.defaultLanguage }}</h5> <h5>默认语言:{{ i18n.defaultLanguage }}</h5>
<h5>当前语言:{{ i18n.activeLanguage.value }}</h5> <h5>当前语言:{{ i18n.activeLanguage }}</h5>
<button v-for="lng of i18n.languages" @click="i18n.activeLanguage = lng.name">{{ lng.title }}</button> <!-- 遍历支持的语言 -->
<button v-for="lng of i18n.languages"
@click="i18n.activeLanguage = lng.name"
>{{ lng.title }}</button>
</template> </template>
``` ```
**说明:**
- 事实上,就算没有`@voerkai18n/vue``@voerkai18n/vite`两件插件相互配合,只需要导入`t`函数也就可以直接使用。这两个插件只是很简单的封装而已。 ## 小结
- 如果要在应用中进行`语言动态切换`,则需要在应用中引入`@voerkai18n/vue`,请参阅`@voerkai18n/vue`插件使用说明。
- `@voerkai18n/vite`的使用请参阅后续说明。 - `@voerkai18n/vue`插件为`Vue`单文件组件提供自动注入`t`函数,可以在`<script>``<template>`中直接使用,在`<script setup>`中需要手动从`language`中导入`t`函数。
- Vue应用的中普通`js/ts`文件需要手动从`language`中导入`t`函数。
- 使用`injectVoerkaI18n()`来实现遍历支持的语言和切换语言的功能。
- 当切换语言时会自动重新渲染组件。

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { VoerkaI18nProvider,VoerkaI18nProviderType,injectVoerkaI18n } from "@voerkai18n/vue" import { injectVoerkaI18n } from "@voerkai18n/vue"
import { reactive } from 'vue' import { reactive } from 'vue'
import { t } from "./languages" import { t } from "./languages"
// This starter template is using Vue 3 <script setup> SFCs // This starter template is using Vue 3 <script setup> SFCs
@ -27,6 +27,7 @@ const i18n = injectVoerkaI18n()
export default { export default {
data() { data() {
console.log(t("data Hello world!"))
return { return {
tabIndex:0, tabIndex:0,
a:this.a a:this.a
@ -51,8 +52,8 @@ export default {
<template> <template>
<div> <div>
<h1 class="navbar" id="title"> <h1 class="navbar">
VoerkaI18n多语言解决方案 - {{ $activeLanguage }} <div class="title">VoerkaI18n多语言解决方案 - {{ $activeLanguage }}</div>
<div class="menu" > <div class="menu" >
<button class="menuitem" :key="lng.name" v-for="lng of i18n.languages" @click="i18n.activeLanguage = lng.name" <button class="menuitem" :key="lng.name" v-for="lng of i18n.languages" @click="i18n.activeLanguage = lng.name"
:style="{ 'outline': lng.name === i18n.activeLanguage ? '2px red solid' : '' }">{{ lng.title }}</button> :style="{ 'outline': lng.name === i18n.activeLanguage ? '2px red solid' : '' }">{{ lng.title }}</button>
@ -62,22 +63,21 @@ export default {
:style="{ 'outline': i18n.activeLanguage.value === 'jp' ? '2px red solid' : '' }">日语</button> --> :style="{ 'outline': i18n.activeLanguage.value === 'jp' ? '2px red solid' : '' }">日语</button> -->
</div> </div>
</h1> </h1>
<span><b>默认语言</b>{{ i18n.defaultLanguage }}&nbsp;&nbsp;&nbsp;&nbsp;<b>当前语言</b>{{ i18n.activeLanguage }}</span> <div class="content">
<div class="tabs"> <span><b>默认语言</b>{{ i18n.defaultLanguage }}&nbsp;&nbsp;&nbsp;&nbsp;<b>当前语言</b>{{ i18n.activeLanguage }}</span>
<div class="tab" title="" > <div class="tabs">
<h3>1.{{t("Hello world!")}}</h3> <div class="tab">
<h3>2.{{ t("中华人民共和国") }} </h3> <h3>1.{{t("Hello world!")}}</h3>
<h3>3.{{ t("迎接中华民族的伟大复兴") }} </h3> <h3>2.{{ t("中华人民共和国") }} </h3>
<h3>3.{{ t("迎接中华民族的伟大复兴") }} </h3>
<China :title="t('中华人民共和国')" /> <China :title="t('中华人民共和国')" />
</div> </div>
<div class="tab" style="flex:2;font-size:small"> <div class="tab" style="flex:2;font-size:small">
<Formatters/> <Formatters/>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
@ -89,26 +89,47 @@ export default {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: #2c3e50; color: #2c3e50;
font-size: 10px; font-size: 10px;
} display: flex;
.navbar{
position: fixed; position: fixed;
margin:0;
top:0; top:0;
left:0; left:0;
width:100%;
height:100%;
}
#app>div{
position: absolute;
top:0;
left:0;
width:100%;
height:100%;
display: flex;
flex-direction: column;
}
#app>div>.content{
flex-grow: 1;
}
.navbar{
margin:0;
width: 100%; width: 100%;
height: 48px; height: 48px;
background: #298df1; background: #298df1;
display: flex;
flex-direction: row;
padding: 12px; padding: 12px;
color:white; color:white;
text-align: left ; text-align: left ;
} }
.navbar>.title{
flex-grow: 1;
}
.navbar>.menu{ .navbar>.menu{
float:right;
top:0; top:0;
margin:0px; margin:0px;
padding-right:20px; padding-right:20px;
display: flex;
align-items: center;
} }
.navbar>.menu>.menuitem{ .navbar>.menu>.menuitem{
padding:8px; padding:8px;
margin:8px; margin:8px;

View File

@ -37,28 +37,19 @@ export default {
</select> </select>
</td></tr> </td></tr>
<tr><td colspan="2" ><b>日期</b></td></tr> <tr><td colspan="2" ><b>日期</b></td></tr>
<tr><td>默认</td><td>{{ t("现在是{ value }", NOW) }}</td></tr> <tr><td colspan="2">
<tr><td>date</td><td>{{ t("现在是{ value | date }", datetime) }}</td></tr> {{t("现在是{ value | date }",new Date()) }}<br>
<tr><td>date|empty</td><td>{{ t("现在是{ value | date | empty }", datetime) }}</td></tr> {{t("现在是{ value | date }","2022/12/9 09:12:36") }}<br>
<tr><td>date|empty('无')</td><td>{{ t("现在是{ value | date | empty('无') }", datetime) }}</td></tr> {{t("现在是{ value | date }",1661084229790)}}<br>
<tr><td>shortdate</td><td>{{ t("现在是{ value | shortdate }", NOW) }}</td></tr> {{t("现在是{ value | date('long') }",new Date())}}<br>
<tr><td>time</td><td>{{ t("现在是{ value | time }", NOW) }}</td></tr> {{t("现在是{ value | date('short') }","2022/12/9 09:12:36") }}<br>
<tr><td>shorttime</td><td>{{ t("现在是{ value | shorttime }", NOW) }}</td></tr> {{t("现在是{ value | date('local') }",1661084229790)}}<br>
<tr><td>year</td><td>{{ t("现在是{ value | year }", NOW) }}</td></tr> {{t("现在是{ value | date('iso') }",1661084229790)}}<br>
<tr><td>month</td><td>{{ t("现在是{ value | month }", NOW) }}</td></tr> {{t("现在是{ value | date('gmt') }",1661084229790)}}<br>
<tr><td>day</td><td>{{ t("现在是{ value | day }", NOW) }}</td></tr> {{t("现在是{ value | date('utc') }",1661084229790)}}<br>
<tr><td>weekdayValue</td><td>{{ t("现在是{ value | weekdayValue }", NOW) }}</td></tr> {{t("现在是{ value | date('YYYY年MM月DD日 HH点mm分ss秒') }",1661084229790)}}<br>
<tr><td>weekday</td><td>{{ t("现在是{ value | weekday }", NOW) }}</td></tr> {{t("现在是{ value | date('YYYY-MM-DD') }",1661084229790)}}
<tr><td>shortWeekday</td><td>{{ t("现在是{ value | shortWeekday }", NOW) }}</td></tr> </td></tr>
<tr><td>monthName</td><td>{{ t("现在是{ value | monthName }", NOW) }}</td></tr>
<tr><td>shorMonthName</td><td>{{ t("现在是{ value | shorMonthName }", NOW) }}</td></tr>
<tr><td colspan="2" ><b>时间</b></td></tr>
<tr><td>hour</td><td>{{ t("现在是{ value | hour }", NOW) }}</td></tr>
<tr><td>hour12</td><td>{{ t("现在是{ value | hour12 }", NOW) }}</td></tr>
<tr><td>minute</td><td>{{ t("现在是{ value | minute }", NOW) }}</td></tr>
<tr><td>second</td><td>{{ t("现在是{ value | second }", NOW) }}</td></tr>
<tr><td>millisecond</td><td>{{ t("现在是{ value | millisecond }", NOW) }}</td></tr>
<tr><td>timestamp</td><td>{{ t("现在是{ value | timestamp }", NOW) }}</td></tr>
<tr><td colspan="2" ><b>货币</b></td></tr> <tr><td colspan="2" ><b>货币</b></td></tr>
<tr><td>currency-cny</td><td>{{ t("商品价格:{ value | currency('CNY','元整',3)}", 788741) }}</td></tr> <tr><td>currency-cny</td><td>{{ t("商品价格:{ value | currency('CNY','元整',3)}", 788741) }}</td></tr>
<tr><td>currency</td><td>{{ t("商品价格:{ value | currency }", 788741) }}</td></tr> <tr><td>currency</td><td>{{ t("商品价格:{ value | currency }", 788741) }}</td></tr>

View File

@ -8,7 +8,7 @@ export default defineConfig({
Inspect(), // localhost:3000/__inspect/ Inspect(), // localhost:3000/__inspect/
Voerkai18nPlugin({ Voerkai18nPlugin({
debug:true, debug:true,
autoImport:true autoImport:false
}), }),
vue()], vue()],
}) })

View File

@ -71,7 +71,7 @@ declare global {
export var VoerkaI18n: VoerkaI18nManager export var VoerkaI18n: VoerkaI18nManager
} }
export type TranslateMessageVars = number | boolean | string | Function export type TranslateMessageVars = number | boolean | string | Function | Date
export interface VoerkaI18nTranslate { export interface VoerkaI18nTranslate {
(message: string, ...args: TranslateMessageVars[]): string (message: string, ...args: TranslateMessageVars[]): string
(message: string, vars?: Record<string, TranslateMessageVars>): string (message: string, vars?: Record<string, TranslateMessageVars>): string

View File

@ -95,7 +95,7 @@ function hasImportTranslateFunction(code){
module.exports = function VoerkaI18nPlugin(opts={}) { module.exports = function VoerkaI18nPlugin(opts={}) {
let options = Object.assign({ let options = Object.assign({
location: "./", // 指定当前工程目录 location: "./", // 指定当前工程目录
autoImport: true, // 是否自动导入t函数 autoImport: false, // 是否自动导入t函数
debug:false, // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单 debug:false, // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单
patterns:[ patterns:[
"!\.(svg|css|json|scss|less|sass)$", "!\.(svg|css|json|scss|less|sass)$",