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]
- (Vite插件)[../tools/vite]
- [Babel插件](../tools/babel)
- [Vite插件](../tools/vite)
当启用了`babel/vite`插件后,就会在编译时自动导入`t`函数。关于插件如何使用请参阅文档。

View File

@ -1,9 +1,15 @@
# 更新日志
## 2023/1/24
- `@voerkai18n/vite`默认不自动导入`t`函数
- 重构`@voerkai18n/vue`,详见`指南`介绍
- 新增`typescript``vue`例子
## 2023/1/11
- 重构`@voerkai18n/react`,支持自动重新渲染
- 修复`@voerkai18n/vite`插件在转码`jsx`组件时存在的idMap错误
- 修复`@voerkai18n/vite`插件在转码`jsx`组件时存在的`idMap`错误
## 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(), // 可选的
Voerkai18nPlugin({
location: "./", // 可选的,指定当前工程目录
autoImport: true, // 是否自动导入t函数
autoImport: false, // 是否自动导入t函数
debug:false, // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单
patterns:[
"!(?<!.vue\?.*).(css|json|scss|less|sass)$", // 排除所有css文件
@ -64,7 +83,7 @@ export default defineConfig({
- `location`:可选的,用来指定当前工程目录,一般情况是不需要配置的,会自动取当前文件夹。并且假设`languages`文件夹在`<location>/src/languages`文件夹下。
- `autoImport`:可选的,默认`true`,用来配置是否自动导入`t`函数。当vue文件没有指定导入时才会自动导入并且根据当前vue文件的路径处理好导入位置。
- `autoImport`:可选的,默认`false`,用来配置是否自动导入`t`函数。当vue文件没有指定导入时才会自动导入并且根据当前vue文件的路径处理好导入位置。
- `debug`:可选的,开启后会在控制台输出一些调试信息,对一般用户没有用。

View File

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

View File

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

View File

@ -37,28 +37,19 @@ export default {
</select>
</td></tr>
<tr><td colspan="2" ><b>日期</b></td></tr>
<tr><td>默认</td><td>{{ t("现在是{ value }", NOW) }}</td></tr>
<tr><td>date</td><td>{{ t("现在是{ value | date }", datetime) }}</td></tr>
<tr><td>date|empty</td><td>{{ t("现在是{ value | date | empty }", datetime) }}</td></tr>
<tr><td>date|empty('无')</td><td>{{ t("现在是{ value | date | empty('无') }", datetime) }}</td></tr>
<tr><td>shortdate</td><td>{{ t("现在是{ value | shortdate }", NOW) }}</td></tr>
<tr><td>time</td><td>{{ t("现在是{ value | time }", NOW) }}</td></tr>
<tr><td>shorttime</td><td>{{ t("现在是{ value | shorttime }", NOW) }}</td></tr>
<tr><td>year</td><td>{{ t("现在是{ value | year }", NOW) }}</td></tr>
<tr><td>month</td><td>{{ t("现在是{ value | month }", NOW) }}</td></tr>
<tr><td>day</td><td>{{ t("现在是{ value | day }", NOW) }}</td></tr>
<tr><td>weekdayValue</td><td>{{ t("现在是{ value | weekdayValue }", NOW) }}</td></tr>
<tr><td>weekday</td><td>{{ t("现在是{ value | weekday }", NOW) }}</td></tr>
<tr><td>shortWeekday</td><td>{{ t("现在是{ value | shortWeekday }", NOW) }}</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">
{{t("现在是{ value | date }",new Date()) }}<br>
{{t("现在是{ value | date }","2022/12/9 09:12:36") }}<br>
{{t("现在是{ value | date }",1661084229790)}}<br>
{{t("现在是{ value | date('long') }",new Date())}}<br>
{{t("现在是{ value | date('short') }","2022/12/9 09:12:36") }}<br>
{{t("现在是{ value | date('local') }",1661084229790)}}<br>
{{t("现在是{ value | date('iso') }",1661084229790)}}<br>
{{t("现在是{ value | date('gmt') }",1661084229790)}}<br>
{{t("现在是{ value | date('utc') }",1661084229790)}}<br>
{{t("现在是{ value | date('YYYY年MM月DD日 HH点mm分ss秒') }",1661084229790)}}<br>
{{t("现在是{ value | date('YYYY-MM-DD') }",1661084229790)}}
</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</td><td>{{ t("商品价格:{ value | currency }", 788741) }}</td></tr>

View File

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

View File

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

View File

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