重构@voerkai18n/vue

This commit is contained in:
wxzhang 2023-01-20 22:00:07 +08:00
parent db71a5386a
commit dfc3344359
45 changed files with 2126 additions and 388 deletions

24
packages/apps/vue-ts-app/.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@ -0,0 +1,18 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support For `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -0,0 +1,24 @@
{
"name": "vue-ts-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@voerkai18n/runtime": "workspace:^1.1.16",
"@voerkai18n/vue": "workspace:^1.0.12",
"vue": "^3.2.45"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.0.0",
"@voerkai18n/vite": "workspace:^1.0.19",
"typescript": "^4.9.3",
"vite": "^4.0.0",
"vite-plugin-inspect": "^0.7.14",
"vue-tsc": "^1.0.11"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,136 @@
<script setup lang="ts">
import { VoerkaI18nProvider,VoerkaI18nProviderType,injectVoerkaI18n } from "@voerkai18n/vue"
import { reactive } from 'vue'
import { t } from "./languages"
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import China from './components/china.vue'
import Formatters from './components/formatters.vue'
let messages = reactive({
name: t('VoerkaI18n多语言解决方案 ')
})
console.log("App=", messages.name)
setTimeout(() => {
messages.name = 'Vue App 3'
}, 5000)
console.log(t("Hello world!"))
const i18n = injectVoerkaI18n()
</script>
<script lang="ts">
export default {
data() {
return {
tabIndex:0,
a:this.a
}
},
watch: {
},
methods: {
async changeLanguage(this:any,value:string) {
this.i18n.activeLanguage = value
console.log("change language =",this.i18n.activeLanguage ,value)
//this.activeLanguage = value
// await this.i18n.change(this.language)
}
}
}
</script>
<template>
<div>
<h1 class="navbar" id="title">
VoerkaI18n多语言解决方案 - {{ $activeLanguage }}
<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>
<!-- <button class="menuitem" @click="i18n.activeLanguage = 'de'"
:style="{ 'outline': i18n.activeLanguage.value === 'de' ? '2px red solid' : '' }">德语</button>
<button class="menuitem" @click="i18n.activeLanguage = 'jp'"
: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>
<div class="tab" style="flex:2;font-size:small">
<Formatters/>
</div>
</div>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
font-size: 10px;
}
.navbar{
position: fixed;
margin:0;
top:0;
left:0;
width: 100%;
height: 48px;
background: #298df1;
padding: 12px;
color:white;
text-align: left ;
}
.navbar>.menu{
float:right;
top:0;
margin:0px;
padding-right:20px;
}
.navbar>.menu>.menuitem{
padding:8px;
margin:8px;
cursor:pointer;
}
.tabs{
width:100%;
padding: 8px;
position: relative;
display: flex;
align-items: flex-start;
flex-direction: row;
}
.tabs > .tab{
position: relative;
padding: 8px;
background: #f3f3f3;
min-height: 500px;
margin:4px;
color:rgb(4, 123, 202);
flex:1;
border-radius: 8px;
}
</style>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@ -0,0 +1,29 @@
<script setup lang="ts">
import { ref } from 'vue'
defineProps({
title: String
})
const count = ref(0)
</script>
<script lang="ts">
export default {
}
</script>
<template>
<div>
<h2>{{ title }}</h2>
<h3>{{ t("成立于{}年",1949)}} </h3>
<h3>{{ t("首都:北京")}} </h3>
</div>
</template>
<style scoped>
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,79 @@
<script setup lang="ts">
defineProps({
title: String
})
</script>
<script lang="ts">
import China from './china.vue'
export default {
components: { China },
data() {
return {
NOW: new Date(),
datetime:null
}
}
}
</script>
<template>
<div class="font-size:6px;">
{{t("Hello world!")}}
<table>
<thead>
<tr style="font-weight:bold;">
<td style="width:200px;">格式化器</td>
<td>内容</td>
</tr>
</thead>
<tbody>
<tr><td colspan="2" >
<select v-model="datetime" >
<option default :value="null">空值</option>
<option :value="NOW">现在</option>
</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" ><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>
<tr><td>capitalizeCurrency</td><td>{{ t("商品价格:{ value | capitalizeCurrency }", 788741) }}</td></tr>
<tr><td>capitalizeCurrency</td><td>{{ t("商品价格:{ value | capitalizeCurrency(true) }", 788741.35) }}</td></tr>
<tr><td colspan="2" ><b>数字</b></td></tr>
<tr><td>number</td><td>{{ t("商品数量:{ value | number }", 1875109.987) }}</td></tr>
</tbody>
</table>
</div>
</template>
<style scoped>
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,34 @@
export default {
"1": "VoerkaI18n多语言解决方案 ",
"2": "EN Hello world!",
"3": "The People's Republic of China",
"4": "Welcome the great rejuvenation of the Chinese nation",
"5": "Founded in {}",
"6": "Capital: Beijing",
"7": "Price{ value | currency }",
"8": "Price{ value | capitalizeCurrency }",
"9": "Price{ value | capitalizeCurrency(true) }",
"10": "Count{ value | number }",
"11": "Now is { value }",
"12": "Now is { value | date }",
"13": "Now is { value | date | empty }",
"14": "Now is { value | date | empty('无') }",
"15": "Now is { value | shortdate }",
"16": "Now is { value | time }",
"17": "Now is { value | shorttime }",
"18": "Now is { value | year }",
"19": "Now is { value | month }",
"20": "Now is { value | day }",
"21": "Now is { value | weekdayValue }",
"22": "Now is { value | weekday }",
"23": "Now is { value | shortWeekday }",
"24": "Now is { value | monthName }",
"25": "Now is { value | shorMonthName }",
"26": "Now is { value | hour }",
"27": "Now is { value | hour12 }",
"28": "Now is { value | minute }",
"29": "Now is { value | second }",
"30": "Now is { value | millisecond }",
"31": "Now is { value | timestamp }",
"32": "Price{ value | currency('CNY','元整',3)}"
}

View File

@ -0,0 +1,112 @@
/**
*/
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// global : true, // 简单地设置为true,代表当前所有格式化器均注册到全局false只在当前scope生效
// global : { // 仅将里面的格式化器注册到全局
// $config:{... }
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
//}, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {
// units : ["Year","Quarter","Month","Week","Day","Hour","Minute","Second","Millisecond","Microsecond"],
// date :{
// long : 'YYYY/MM/DD HH:mm:ss',
// short : "YYYY/MM/DD",
// format : "local"
// },
// quarter : {
// long : ["First Quarter","Second Quarter","Third Quarter","Fourth Quarter"],
// short : ["Q1","Q2","Q3","Q4"],
// format : "short"
// },
// month:{
// long : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
// short : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"],
// format : "long" // 0-长名称1-短名称2-数字
// },
// weekday:{
// long : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
// short : ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"],
// format : "long", // 0-长名称1-短名称2-数字
// },
// time : {
// long : "HH:mm:ss",
// short : "HH:mm:ss",
// format : 'local'
// },
// timeSlots : {
// slots : [12],
// lowerCases : ["am","pm"],
// upperCases : ["AM","PM"]
// },
// relativeTime : {
// units : ["seconds","minutes","hours","days","weeks","months","years"],
// now : "Now",
// before : "{value} {unit} ago",
// after : "after {value} {unit}"
// }
// },
// currency : {
// default : "{symbol}{value}{unit}",
// long : "{prefix} {symbol}{value}{unit}{suffix}",
// short : "{symbol}{value}{unit}",
// custom : "{prefix} {symbol}{value}{unit}{suffix}",
// format : "default",
// //--
// units : [""," thousands"," millions"," billions"," trillions"], //千,百万,十亿,万亿
// radix : 3, // 进制即三位一进中文是4位一进
// symbol : "$", // 符号
// prefix : "USD", // 前缀
// suffix : "", // 后缀
// division : 3, // ,分割位
// precision : 2, // 精度
// },
// number : {
// division : 3, // , 分割位3代表每3位添加一个,
// precision : 0 // 精度,即保留小数点位置,0代表不限
// },
// empty:{
// //values : [], // 可选定义空值如果想让0,''也为空值可以指定values=[0,'']
// escape : "", // 当空值时显示的备用值
// next : 'break' // 当空值时下一步的行为: break=中止;skip=跳过
// },
// error : {
// //当错误时显示的内容支持的插值变量有message=错误信息,error=错误类名,也可以是一个返回上面内容的同步函数
// escape : null, // 默认当错误时显示空内容
// next : 'break' // 当出错时下一步的行为: break=中止;skip=忽略
// },
// fileSize:{
// brief : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB","NB","DB"],
// whole : ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "TeraBytes", "PetaBytes", "ExaBytes", "ZetaBytes", "YottaBytes","DoggaBytes"],
// precision: 2 // 小数精度
// }
// },
// 改变特定数据类型的默认格式化器
// $types:{
// Date : dateFormatter,
// Null : value =>"",
// Undefined: value =>"",
// Error : value => "ERROR",
// Boolean : value =>value ? "True":"False",
// Number : numberFormartter
// }
// 以下可以自定义编写格式化器
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
}

View File

@ -0,0 +1,112 @@
/**
*/
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// global : true, // 简单地设置为true,代表当前所有格式化器均注册到全局false只在当前scope生效
// global : { // 仅将里面的格式化器注册到全局
// $config:{... }
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
//}, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {
// units : ["Year","Quarter","Month","Week","Day","Hour","Minute","Second","Millisecond","Microsecond"],
// date :{
// long : 'YYYY/MM/DD HH:mm:ss',
// short : "YYYY/MM/DD",
// format : "local"
// },
// quarter : {
// long : ["First Quarter","Second Quarter","Third Quarter","Fourth Quarter"],
// short : ["Q1","Q2","Q3","Q4"],
// format : "short"
// },
// month:{
// long : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
// short : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"],
// format : "long" // 0-长名称1-短名称2-数字
// },
// weekday:{
// long : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
// short : ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"],
// format : "long", // 0-长名称1-短名称2-数字
// },
// time : {
// long : "HH:mm:ss",
// short : "HH:mm:ss",
// format : 'local'
// },
// timeSlots : {
// slots : [12],
// lowerCases : ["am","pm"],
// upperCases : ["AM","PM"]
// },
// relativeTime : {
// units : ["seconds","minutes","hours","days","weeks","months","years"],
// now : "Now",
// before : "{value} {unit} ago",
// after : "after {value} {unit}"
// }
// },
// currency : {
// default : "{symbol}{value}{unit}",
// long : "{prefix} {symbol}{value}{unit}{suffix}",
// short : "{symbol}{value}{unit}",
// custom : "{prefix} {symbol}{value}{unit}{suffix}",
// format : "default",
// //--
// units : [""," thousands"," millions"," billions"," trillions"], //千,百万,十亿,万亿
// radix : 3, // 进制即三位一进中文是4位一进
// symbol : "$", // 符号
// prefix : "USD", // 前缀
// suffix : "", // 后缀
// division : 3, // ,分割位
// precision : 2, // 精度
// },
// number : {
// division : 3, // , 分割位3代表每3位添加一个,
// precision : 0 // 精度,即保留小数点位置,0代表不限
// },
// empty:{
// //values : [], // 可选定义空值如果想让0,''也为空值可以指定values=[0,'']
// escape : "", // 当空值时显示的备用值
// next : 'break' // 当空值时下一步的行为: break=中止;skip=跳过
// },
// error : {
// //当错误时显示的内容支持的插值变量有message=错误信息,error=错误类名,也可以是一个返回上面内容的同步函数
// escape : null, // 默认当错误时显示空内容
// next : 'break' // 当出错时下一步的行为: break=中止;skip=忽略
// },
// fileSize:{
// brief : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB","NB","DB"],
// whole : ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "TeraBytes", "PetaBytes", "ExaBytes", "ZetaBytes", "YottaBytes","DoggaBytes"],
// precision: 2 // 小数精度
// }
// },
// 改变特定数据类型的默认格式化器
// $types:{
// Date : dateFormatter,
// Null : value =>"",
// Undefined: value =>"",
// Error : value => "ERROR",
// Boolean : value =>value ? "True":"False",
// Number : numberFormartter
// }
// 以下可以自定义编写格式化器
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
}

View File

@ -0,0 +1,34 @@
export default {
"VoerkaI18n多语言解决方案 ": 1,
"Hello world!": 2,
"中华人民共和国": 3,
"迎接中华民族的伟大复兴": 4,
"成立于{}年": 5,
"首都:北京": 6,
"商品价格:{ value | currency }": 7,
"商品价格:{ value | capitalizeCurrency }": 8,
"商品价格:{ value | capitalizeCurrency(true) }": 9,
"商品数量:{ value | number }": 10,
"现在是{ value }": 11,
"现在是{ value | date }": 12,
"现在是{ value | date | empty }": 13,
"现在是{ value | date | empty('无') }": 14,
"现在是{ value | shortdate }": 15,
"现在是{ value | time }": 16,
"现在是{ value | shorttime }": 17,
"现在是{ value | year }": 18,
"现在是{ value | month }": 19,
"现在是{ value | day }": 20,
"现在是{ value | weekdayValue }": 21,
"现在是{ value | weekday }": 22,
"现在是{ value | shortWeekday }": 23,
"现在是{ value | monthName }": 24,
"现在是{ value | shorMonthName }": 25,
"现在是{ value | hour }": 26,
"现在是{ value | hour12 }": 27,
"现在是{ value | minute }": 28,
"现在是{ value | second }": 29,
"现在是{ value | millisecond }": 30,
"现在是{ value | timestamp }": 31,
"商品价格:{ value | currency('CNY','元整',3)}": 32
}

View File

@ -0,0 +1,50 @@
import messageIds from "./idMap" // 语言ID映射文件
import runtime from "@voerkai18n/runtime"
const { translate,VoerkaI18nScope } = runtime
import defaultFormatters from "./formatters/zh" // 默认语言格式化器
const activeFormatters = defaultFormatters
import defaultMessages from "./zh"
const activeMessages = defaultMessages
// 语言配置文件
const scopeSettings = {
"languages": [
{
"name": "zh",
"title": "zh"
},
{
"name": "en",
"title": "en"
}
],
"defaultLanguage": "zh",
"activeLanguage": "zh",
"namespaces": {}
}
const formatters = {
'zh' : defaultFormatters,
'en' : ()=>import("./formatters/en")
}
// 语言包加载器
const loaders = {
"en" : ()=>import("./en")
}
// 语言作用域
const scope = new VoerkaI18nScope({
...scopeSettings, // languages,defaultLanguage,activeLanguage,namespaces,formatters
id : "vue-ts-app", // 当前作用域的id自动取当前工程的package.json的name
debug : false, // 是否在控制台输出高度信息
default : defaultMessages, // 默认语言包
messages : activeMessages, // 当前语言包
idMap : messageIds, // 消息id映射列表
formatters, // 扩展自定义格式化器
loaders // 语言包加载器
})
// 翻译函数
const scopedTtranslate = translate.bind(scope)
export {
scopedTtranslate as t,
scope as i18nScope
}

View File

@ -0,0 +1,15 @@
{
"languages": [
{
"name": "zh",
"title": "zh"
},
{
"name": "en",
"title": "en"
}
],
"defaultLanguage": "zh",
"activeLanguage": "zh",
"namespaces": {}
}

View File

@ -0,0 +1,227 @@
{
"VoerkaI18n多语言解决方案 ": {
"en": "VoerkaI18n多语言解决方案 ",
"de": "VoerkaI18n multilingual solution ",
"$file": [
"App.vue"
]
},
"Hello world!": {
"en": "EN Hello world!",
"de": "DE Hello world!",
"$file": [
"App.vue",
"components\\formatters.vue"
]
},
"中华人民共和国": {
"en": "The People's Republic of China",
"de": "中华人民共和国",
"$file": [
"App.vue"
]
},
"迎接中华民族的伟大复兴": {
"en": "Welcome the great rejuvenation of the Chinese nation",
"de": "迎接中华民族的伟大复兴",
"$file": [
"App.vue"
]
},
"成立于{}年": {
"en": "Founded in {}",
"de": "成立于{}年",
"$file": [
"components\\china.vue"
]
},
"首都:北京": {
"en": "Capital: Beijing",
"de": "首都:北京",
"$file": [
"components\\china.vue"
]
},
"商品价格:{ value | currency }": {
"en": "Price{ value | currency }",
"de": "DE Price{ value | currency }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | capitalizeCurrency }": {
"en": "Price{ value | capitalizeCurrency }",
"de": "商品价格:{ value | capitalizeCurrency }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | capitalizeCurrency(true) }": {
"en": "Price{ value | capitalizeCurrency(true) }",
"de": "商品价格:{ value | capitalizeCurrency(true) }",
"$file": [
"components\\formatters.vue"
]
},
"商品数量:{ value | number }": {
"en": "Count{ value | number }",
"de": "商品数量:{ value | number }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value }": {
"en": "Now is { value }",
"de": "D现在是{ value }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date }": {
"en": "Now is { value | date }",
"de": "D现在是{ value | date }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date | empty }": {
"en": "Now is { value | date | empty }",
"de": "D现在是{ value | date | empty }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date | empty('无') }": {
"en": "Now is { value | date | empty('无') }",
"de": "D现在是{ value | date | empty('无') }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortdate }": {
"en": "Now is { value | shortdate }",
"de": "D现在是{ value | shortdate }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | time }": {
"en": "Now is { value | time }",
"de": "D现在是{ value | time }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorttime }": {
"en": "Now is { value | shorttime }",
"de": "D现在是{ value | shorttime }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | year }": {
"en": "Now is { value | year }",
"de": "D现在是{ value | year }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | month }": {
"en": "Now is { value | month }",
"de": "D现在是{ value | month }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | day }": {
"en": "Now is { value | day }",
"de": "D现在是{ value | day }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekdayValue }": {
"en": "Now is { value | weekdayValue }",
"de": "D现在是{ value | weekdayValue }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekday }": {
"en": "Now is { value | weekday }",
"de": "D现在是{ value | weekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortWeekday }": {
"en": "Now is { value | shortWeekday }",
"de": "D现在是{ value | shortWeekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | monthName }": {
"en": "Now is { value | monthName }",
"de": "D现在是{ value | monthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorMonthName }": {
"en": "Now is { value | shorMonthName }",
"de": "D现在是{ value | shorMonthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour }": {
"en": "Now is { value | hour }",
"de": "D现在是{ value | hour }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour12 }": {
"en": "Now is { value | hour12 }",
"de": "D现在是{ value | hour12 }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | minute }": {
"en": "Now is { value | minute }",
"de": "D现在是{ value | minute }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | second }": {
"en": "Now is { value | second }",
"de": "D现在是{ value | second }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | millisecond }": {
"en": "Now is { value | millisecond }",
"de": "D现在是{ value | millisecond }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | timestamp }": {
"en": "Now is { value | timestamp }",
"de": "D现在是{ value | timestamp }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | currency('CNY','元整',3)}": {
"en": "Price{ value | currency('CNY','元整',3)}",
"de": "D商品价格{ value | currency('CNY','元整',3)}",
"$file": [
"components\\formatters.vue"
]
}
}

View File

@ -0,0 +1,34 @@
export default {
"1": "VoerkaI18n多语言解决方案 ",
"2": "Hello world!",
"3": "中华人民共和国",
"4": "迎接中华民族的伟大复兴",
"5": "成立于{}年",
"6": "首都:北京",
"7": "商品价格:{ value | currency }",
"8": "商品价格:{ value | capitalizeCurrency }",
"9": "商品价格:{ value | capitalizeCurrency(true) }",
"10": "商品数量:{ value | number }",
"11": "现在是{ value }",
"12": "现在是{ value | date }",
"13": "现在是{ value | date | empty }",
"14": "现在是{ value | date | empty('无') }",
"15": "现在是{ value | shortdate }",
"16": "现在是{ value | time }",
"17": "现在是{ value | shorttime }",
"18": "现在是{ value | year }",
"19": "现在是{ value | month }",
"20": "现在是{ value | day }",
"21": "现在是{ value | weekdayValue }",
"22": "现在是{ value | weekday }",
"23": "现在是{ value | shortWeekday }",
"24": "现在是{ value | monthName }",
"25": "现在是{ value | shorMonthName }",
"26": "现在是{ value | hour }",
"27": "现在是{ value | hour12 }",
"28": "现在是{ value | minute }",
"29": "现在是{ value | second }",
"30": "现在是{ value | millisecond }",
"31": "现在是{ value | timestamp }",
"32": "商品价格:{ value | currency('CNY','元整',3)}"
}

View File

@ -0,0 +1,34 @@
export default {
"1": "VoerkaI18n多语言解决方案 ",
"2": "Hello world!",
"3": "中华人民共和国",
"4": "迎接中华民族的伟大复兴",
"5": "成立于{}年",
"6": "首都:北京",
"7": "商品价格:{ value | currency }",
"8": "商品价格:{ value | capitalizeCurrency }",
"9": "商品价格:{ value | capitalizeCurrency(true) }",
"10": "商品数量:{ value | number }",
"11": "现在是{ value }",
"12": "现在是{ value | date }",
"13": "现在是{ value | date | empty }",
"14": "现在是{ value | date | empty('无') }",
"15": "现在是{ value | shortdate }",
"16": "现在是{ value | time }",
"17": "现在是{ value | shorttime }",
"18": "现在是{ value | year }",
"19": "现在是{ value | month }",
"20": "现在是{ value | day }",
"21": "现在是{ value | weekdayValue }",
"22": "现在是{ value | weekday }",
"23": "现在是{ value | shortWeekday }",
"24": "现在是{ value | monthName }",
"25": "现在是{ value | shorMonthName }",
"26": "现在是{ value | hour }",
"27": "现在是{ value | hour12 }",
"28": "现在是{ value | minute }",
"29": "现在是{ value | second }",
"30": "现在是{ value | millisecond }",
"31": "现在是{ value | timestamp }",
"32": "商品价格:{ value | currency('CNY','元整',3)}"
}

View File

@ -0,0 +1,11 @@
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')

View File

@ -0,0 +1,81 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@ -0,0 +1,14 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Inspect from 'vite-plugin-inspect'
import Voerkai18nPlugin from "@voerkai18n/vite"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
Inspect(), // localhost:3000/__inspect/
Voerkai18nPlugin({
debug:true,
autoImport:true
}),
vue()],
})

View File

@ -11,6 +11,7 @@
},
"dependencies": {
"@voerkai18n/cli": "workspace:^1.0.11",
"@voerkai18n/runtime": "workspace:^1.1.16",
"@voerkai18n/vite": "workspace:^1.0.7",
"@voerkai18n/vue": "workspace:^1.0.0",
"vue": "^3.2.37"
@ -27,7 +28,7 @@
"@voerkai18n/babel": "workspace:^1.0.0",
"babel-preset-env": "^1.7.0",
"core-js": "^3.21.1",
"vite": "^2.9.14",
"vite-plugin-inspect": "^0.4.3"
"vite": "^4.0.4",
"vite-plugin-inspect": "^0.7.14"
}
}

View File

@ -1,3 +1,3 @@
{
"2": "The People's Republic of China!!!"
"2": "Hello world-Patch!"
}

View File

@ -1,6 +1,6 @@
<script setup>
import { reactive } from 'vue'
import { t } from "./languages"
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import China from './components/china.vue'
@ -11,12 +11,12 @@ let messages = reactive({
})
console.log("App=", messages.name)
setTimeout(() => {
messages.name = 'Vue App 2'
}, 5000)
// console.log(t("Hello world!"))
console.log(t("Hello world!"))
</script>
<script>
import { reactive } from 'vue'
@ -43,22 +43,24 @@ export default {
<template>
<div>
<h1 class="navbar" id="title">
VoerkaI18n多语言解决方案
VoerkaI18n多语言解决方案 - {{ $activeLanguage }}
<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.value ? '2px red solid' : '' }">{{ lng.title
}}</button>
<button class="menuitem" @click="i18n.activeLanguage = 'de'"
<!-- <button class="menuitem" @click="i18n.activeLanguage = 'de'"
:style="{ 'outline': i18n.activeLanguage.value === 'de' ? '2px red solid' : '' }">德语</button>
<button class="menuitem" @click="i18n.activeLanguage = 'jp'"
:style="{ 'outline': i18n.activeLanguage.value === 'jp' ? '2px red solid' : '' }">日语</button>
: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.value }}</span>
<div class="tabs">
<div class="tab" title="" >
<h3>{{ t("中华人民共和国") }} </h3>
<h3>{{ t("迎接中华民族的伟大复兴") }} </h3>
<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">
@ -78,7 +80,7 @@ export default {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top:80px;
margin-top:80px;
}
.navbar{
position: fixed;

View File

@ -37,7 +37,7 @@ export default {
</select>
</td></tr>
<tr><td colspan="2" ><b>日期</b></td></tr>
<!-- <tr><td>默认</td><td>{{ t("现在是{ value }", NOW) }}</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>
@ -59,8 +59,8 @@ export default {
<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>currency-cny</td><td>{{ t("商品价格:{ value | currency('CNY','元整',3)}", 788741) }}</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>
<tr><td>capitalizeCurrency</td><td>{{ t("商品价格:{ value | capitalizeCurrency }", 788741) }}</td></tr>
<tr><td>capitalizeCurrency</td><td>{{ t("商品价格:{ value | capitalizeCurrency(true) }", 788741.35) }}</td></tr>

View File

@ -1,33 +1,34 @@
export default {
"1": "Hello world!(EN)",
"2": "The People's Republic of China",
"3": "Welcome the great rejuvenation of the Chinese nation",
"4": "Founded in {}",
"5": "Capital: Beijing",
"6": "VoerkaI18n多语言解决方案 ",
"7": "Now is { value | date }",
"8": "Now is { value | date | empty }",
"9": "Now is { value | date | empty('无') }",
"10": "现在是{ value | shortdate }",
"11": "现在是{ value | time }",
"12": "现在是{ value | shorttime }",
"13": "现在是{ value | year }",
"14": "现在是{ value | month }",
"15": "现在是{ value | day }",
"16": "现在是{ value | weekdayValue }",
"17": "现在是{ value | weekday }",
"18": "现在是{ value | shortWeekday }",
"19": "现在是{ value | monthName }",
"20": "现在是{ value | shorMonthName }",
"21": "现在是{ value | hour }",
"22": "现在是{ value | hour12 }",
"23": "现在是{ value | minute }",
"24": "现在是{ value | second }",
"25": "现在是{ value | millisecond }",
"26": "现在是{ value | timestamp }",
"27": "商品价格:{ value | currency('US ','元整',3)}",
"28": "商品价格:{ value | currency }",
"29": "商品价格:{ value | capitalizeCurrency }",
"30": "商品价格:{ value | capitalizeCurrency(true) }",
"31": "商品数量:{ value | number }"
"1": "VoerkaI18n多语言解决方案 ",
"2": "EN Hello world!",
"3": "The People's Republic of China",
"4": "Welcome the great rejuvenation of the Chinese nation",
"5": "Founded in {}",
"6": "Capital: Beijing",
"7": "Price{ value | currency }",
"8": "Price{ value | capitalizeCurrency }",
"9": "Price{ value | capitalizeCurrency(true) }",
"10": "Count{ value | number }",
"11": "Now is { value }",
"12": "Now is { value | date }",
"13": "Now is { value | date | empty }",
"14": "Now is { value | date | empty('无') }",
"15": "Now is { value | shortdate }",
"16": "Now is { value | time }",
"17": "Now is { value | shorttime }",
"18": "Now is { value | year }",
"19": "Now is { value | month }",
"20": "Now is { value | day }",
"21": "Now is { value | weekdayValue }",
"22": "Now is { value | weekday }",
"23": "Now is { value | shortWeekday }",
"24": "Now is { value | monthName }",
"25": "Now is { value | shorMonthName }",
"26": "Now is { value | hour }",
"27": "Now is { value | hour12 }",
"28": "Now is { value | minute }",
"29": "Now is { value | second }",
"30": "Now is { value | millisecond }",
"31": "Now is { value | timestamp }",
"32": "Price{ value | currency('CNY','元整',3)}"
}

View File

@ -1,33 +1,34 @@
export default {
"Hello world!": 1,
"中华人民共和国": 2,
"迎接中华民族的伟大复兴": 3,
"成立于{}年": 4,
"首都:北京": 5,
"VoerkaI18n多语言解决方案 ": 6,
"现在是{ value | date }": 7,
"现在是{ value | date | empty }": 8,
"现在是{ value | date | empty('无') }": 9,
"现在是{ value | shortdate }": 10,
"现在是{ value | time }": 11,
"现在是{ value | shorttime }": 12,
"现在是{ value | year }": 13,
"现在是{ value | month }": 14,
"现在是{ value | day }": 15,
"现在是{ value | weekdayValue }": 16,
"现在是{ value | weekday }": 17,
"现在是{ value | shortWeekday }": 18,
"现在是{ value | monthName }": 19,
"现在是{ value | shorMonthName }": 20,
"现在是{ value | hour }": 21,
"现在是{ value | hour12 }": 22,
"现在是{ value | minute }": 23,
"现在是{ value | second }": 24,
"现在是{ value | millisecond }": 25,
"现在是{ value | timestamp }": 26,
"商品价格:{ value | currency('CNY','元整',3)}": 27,
"商品价格:{ value | currency }": 28,
"商品价格:{ value | capitalizeCurrency }": 29,
"商品价格:{ value | capitalizeCurrency(true) }": 30,
"商品数量:{ value | number }": 31
"VoerkaI18n多语言解决方案 ": 1,
"Hello world!": 2,
"中华人民共和国": 3,
"迎接中华民族的伟大复兴": 4,
"成立于{}年": 5,
"首都:北京": 6,
"商品价格:{ value | currency }": 7,
"商品价格:{ value | capitalizeCurrency }": 8,
"商品价格:{ value | capitalizeCurrency(true) }": 9,
"商品数量:{ value | number }": 10,
"现在是{ value }": 11,
"现在是{ value | date }": 12,
"现在是{ value | date | empty }": 13,
"现在是{ value | date | empty('无') }": 14,
"现在是{ value | shortdate }": 15,
"现在是{ value | time }": 16,
"现在是{ value | shorttime }": 17,
"现在是{ value | year }": 18,
"现在是{ value | month }": 19,
"现在是{ value | day }": 20,
"现在是{ value | weekdayValue }": 21,
"现在是{ value | weekday }": 22,
"现在是{ value | shortWeekday }": 23,
"现在是{ value | monthName }": 24,
"现在是{ value | shorMonthName }": 25,
"现在是{ value | hour }": 26,
"现在是{ value | hour12 }": 27,
"现在是{ value | minute }": 28,
"现在是{ value | second }": 29,
"现在是{ value | millisecond }": 30,
"现在是{ value | timestamp }": 31,
"商品价格:{ value | currency('CNY','元整',3)}": 32
}

View File

@ -1,10 +1,9 @@
import messageIds from "./idMap.js" // 语言ID映射文件
import runtime from "./runtime.js" // 运行时
const { translate,i18nScope } = runtime
import defaultFormatters from "./formatters/zh.js" // 默认语言格式化器
const activeFormatters = defaultFormatters // 激活语言格式化器
import runtime from "@voerkai18n/runtime"
const { translate,VoerkaI18nScope } = runtime
import defaultFormatters from "./formatters/zh"
const activeFormatters = defaultFormatters
import defaultMessages from "./zh.js"
const activeMessages = defaultMessages
@ -29,7 +28,6 @@ const scopeSettings = {
"activeLanguage": "zh",
"namespaces": {}
}
// 格式化器
const formatters = {
'zh' : defaultFormatters,
'en' : ()=>import("./formatters/en.js"),
@ -42,7 +40,7 @@ const loaders = {
}
// 语言作用域
const scope = new i18nScope({
const scope = new VoerkaI18nScope({
...scopeSettings, // languages,defaultLanguage,activeLanguage,namespaces,formatters
id : "vueapp", // 当前作用域的id自动取当前工程的package.json的name
debug : false, // 是否在控制台输出高度信息

View File

@ -1,219 +1,227 @@
{
"Hello world!": {
"en": "Hello world!(EN)",
"VoerkaI18n多语言解决方案 ": {
"en": "VoerkaI18n多语言解决方案 ",
"de": "VoerkaI18n multilingual solution ",
"$file": [
"App.vue"
],
"de": "Hello world!(DE)"
]
},
"Hello world!": {
"en": "EN Hello world!",
"de": "DE Hello world!",
"$file": [
"App.vue",
"components\\formatters.vue"
]
},
"中华人民共和国": {
"en": "The People's Republic of China",
"de": "中华人民共和国",
"$file": [
"App.vue"
],
"de": "中华人民共和国(DE)"
]
},
"迎接中华民族的伟大复兴": {
"en": "Welcome the great rejuvenation of the Chinese nation",
"de": "迎接中华民族的伟大复兴",
"$file": [
"App.vue"
],
"de": "迎接中华民族的伟大复兴(DE)"
]
},
"成立于{}年": {
"en": "Founded in {}",
"de": "成立于{}年",
"$file": [
"components\\china.vue"
],
"de": "成立于{}年(DE)"
]
},
"首都:北京": {
"en": "Capital: Beijing",
"de": "首都:北京",
"$file": [
"components\\china.vue"
],
"de": "首都:北京(DE)"
},
"VoerkaI18n多语言解决方案 ": {
"en": "VoerkaI18n多语言解决方案 ",
"$file": [
"App.vue"
],
"de": "VoerkaI18n多语言解决方案 (DE)"
},
"现在是{ value | date }": {
"en": "Now is { value | date }",
"$file": [
"components\\formatters.vue"
],
"de": "DE Now is { value | date }(DE)"
},
"现在是{ value | date | empty }": {
"en": "Now is { value | date | empty }",
"de": "Now is { value | date | empty }(DE)",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date | empty('无') }": {
"en": "Now is { value | date | empty('无') }",
"de": "Now is { value | date | empty('无') } (DE) ",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortdate }": {
"en": "现在是{ value | shortdate }",
"de": "现在是{ value | shortdate }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | time }": {
"en": "现在是{ value | time }",
"de": "现在是{ value | time }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorttime }": {
"en": "现在是{ value | shorttime }",
"de": "现在是{ value | shorttime }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | year }": {
"en": "现在是{ value | year }",
"de": "现在是{ value | year }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | month }": {
"en": "现在是{ value | month }",
"de": "现在是{ value | month }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | day }": {
"en": "现在是{ value | day }",
"de": "现在是{ value | day }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekdayValue }": {
"en": "现在是{ value | weekdayValue }",
"de": "现在是{ value | weekdayValue }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekday }": {
"en": "现在是{ value | weekday }",
"de": "现在是{ value | weekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortWeekday }": {
"en": "现在是{ value | shortWeekday }",
"de": "现在是{ value | shortWeekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | monthName }": {
"en": "现在是{ value | monthName }",
"de": "现在是{ value | monthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorMonthName }": {
"en": "现在是{ value | shorMonthName }",
"de": "现在是{ value | shorMonthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour }": {
"en": "现在是{ value | hour }",
"de": "现在是{ value | hour }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour12 }": {
"en": "现在是{ value | hour12 }",
"de": "现在是{ value | hour12 }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | minute }": {
"en": "现在是{ value | minute }",
"de": "现在是{ value | minute }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | second }": {
"en": "现在是{ value | second }",
"de": "现在是{ value | second }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | millisecond }": {
"en": "现在是{ value | millisecond }",
"de": "现在是{ value | millisecond }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | timestamp }": {
"en": "现在是{ value | timestamp }",
"de": "现在是{ value | timestamp }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | currency('CNY','元整',3)}": {
"en": "商品价格:{ value | currency('US ','元整',3)}",
"de": "商品价格:{ value | currency('CNY','元整',3)}",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | currency }": {
"en": "商品价格{ value | currency }",
"de": "商品价格{ value | currency }",
"en": "Price{ value | currency }",
"de": "DE Price{ value | currency }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | capitalizeCurrency }": {
"en": "商品价格{ value | capitalizeCurrency }",
"en": "Price{ value | capitalizeCurrency }",
"de": "商品价格:{ value | capitalizeCurrency }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | capitalizeCurrency(true) }": {
"en": "商品价格{ value | capitalizeCurrency(true) }",
"en": "Price{ value | capitalizeCurrency(true) }",
"de": "商品价格:{ value | capitalizeCurrency(true) }",
"$file": [
"components\\formatters.vue"
]
},
"商品数量:{ value | number }": {
"en": "商品数量{ value | number }",
"en": "Count{ value | number }",
"de": "商品数量:{ value | number }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value }": {
"en": "Now is { value }",
"de": "D现在是{ value }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date }": {
"en": "Now is { value | date }",
"de": "D现在是{ value | date }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date | empty }": {
"en": "Now is { value | date | empty }",
"de": "D现在是{ value | date | empty }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | date | empty('无') }": {
"en": "Now is { value | date | empty('无') }",
"de": "D现在是{ value | date | empty('无') }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortdate }": {
"en": "Now is { value | shortdate }",
"de": "D现在是{ value | shortdate }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | time }": {
"en": "Now is { value | time }",
"de": "D现在是{ value | time }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorttime }": {
"en": "Now is { value | shorttime }",
"de": "D现在是{ value | shorttime }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | year }": {
"en": "Now is { value | year }",
"de": "D现在是{ value | year }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | month }": {
"en": "Now is { value | month }",
"de": "D现在是{ value | month }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | day }": {
"en": "Now is { value | day }",
"de": "D现在是{ value | day }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekdayValue }": {
"en": "Now is { value | weekdayValue }",
"de": "D现在是{ value | weekdayValue }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | weekday }": {
"en": "Now is { value | weekday }",
"de": "D现在是{ value | weekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shortWeekday }": {
"en": "Now is { value | shortWeekday }",
"de": "D现在是{ value | shortWeekday }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | monthName }": {
"en": "Now is { value | monthName }",
"de": "D现在是{ value | monthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | shorMonthName }": {
"en": "Now is { value | shorMonthName }",
"de": "D现在是{ value | shorMonthName }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour }": {
"en": "Now is { value | hour }",
"de": "D现在是{ value | hour }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | hour12 }": {
"en": "Now is { value | hour12 }",
"de": "D现在是{ value | hour12 }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | minute }": {
"en": "Now is { value | minute }",
"de": "D现在是{ value | minute }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | second }": {
"en": "Now is { value | second }",
"de": "D现在是{ value | second }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | millisecond }": {
"en": "Now is { value | millisecond }",
"de": "D现在是{ value | millisecond }",
"$file": [
"components\\formatters.vue"
]
},
"现在是{ value | timestamp }": {
"en": "Now is { value | timestamp }",
"de": "D现在是{ value | timestamp }",
"$file": [
"components\\formatters.vue"
]
},
"商品价格:{ value | currency('CNY','元整',3)}": {
"en": "Price{ value | currency('CNY','元整',3)}",
"de": "D商品价格{ value | currency('CNY','元整',3)}",
"$file": [
"components\\formatters.vue"
]
}
}

View File

@ -1,7 +1,7 @@
import { createApp } from 'vue'
import App from './App.vue'
import i18nPlugin from '@voerkai18n/vue'
import { t,i18nScope } from './languages'
import { i18nScope } from './languages'
i18nScope.registerDefaultLoader(async (language,scope)=>{
return await (await fetch(`/languages/${scope.id}/${language}.json`)).json()
@ -9,6 +9,6 @@ i18nScope.registerDefaultLoader(async (language,scope)=>{
const app = createApp(App)
app.use(i18nPlugin,{ t,i18nScope })
app.use(i18nPlugin,{ i18nScope })
app.mount('#app')

View File

@ -12,12 +12,20 @@ export default defineConfig({
//legacy(),
//babel(),
Inspect(), // localhost:3000/__inspect/
Voerkai18nPlugin({debug:true}),
Voerkai18nPlugin({
debug:true,
autoImport:false
}),
vue()
],
resolve:{
alias:{
"voerkai18n":"./languages/index.js"
}
}
},
build:{
rollupOptions:{
include:["@voerkai18n/vue"]
}
}
})

View File

@ -4,8 +4,7 @@
"description": "格式化器,提供对要翻译文本的转换功能",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"release": "pnpm autopublish"
"test": "echo \"Error: no test specified\" && exit 1"
},
"exports": {
"currency": "./currency.formatters.js",
@ -16,8 +15,5 @@
"dependencies": {
"dayjs": "^1.11.0"
},
"devDependencies": {
"@voerkai18n/autopublish": "workspace:^1.0.2"
},
"lastPublish": "2023-01-12T13:53:59+08:00"
}

View File

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

9
packages/vite/index.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import type { PluginOption } from "vite"
export interface Voerkai18nPluginOptions{
location?: string // 指定当前工程目录
autoImport?: boolean // 是否自动导入t函数
debug?:boolean // 是否输出调试信息,当=true时在控制台输出转换匹配的文件清单
patterns?:(string | RegExp)[]
}
export default function Voerkai18nPlugin(options:Voerkai18nPluginOptions):PluginOption

View File

@ -7,7 +7,7 @@ const { fileMatcher,getProjectRootFolder,getProjectLanguageFolder } = require("@
const TranslateRegex =/(?<=\bt\(\s*("|'){1})(?<text>[^\1]*?)(?=(\1\s*\))|(\1\s*\,))/gm
// 匹配正则表达式
const importTRegex = /^[^\w\r\n]*import\s*\{(.*)\bt\b(.*)\}\sfrom/gm
const importTRegex = /^[^\w\r\n\s]*import\s*\{(.*)\bt\b(.*)\}\s*from/gm
/**
@ -28,11 +28,19 @@ const importTRegex = /^[^\w\r\n]*import\s*\{(.*)\bt\b(.*)\}\sfrom/gm
searchIdMapFiles.push(path.join(location,"languages/idMap.js"))
searchIdMapFiles.push(path.join(location,"idMap.js"))
searchIdMapFiles.push(path.join(location,"src","languages/idMap.ts"))
searchIdMapFiles.push(path.join(location,"languages/idMap.ts"))
searchIdMapFiles.push(path.join(location,"idMap.ts"))
let projectRoot = getProjectRootFolder(location)
searchIdMapFiles.push(path.join(projectRoot,"src","languages/idMap.js"))
searchIdMapFiles.push(path.join(projectRoot,"languages/idMap.js"))
searchIdMapFiles.push(path.join(projectRoot,"idMap.js"))
searchIdMapFiles.push(path.join(projectRoot,"src","languages/idMap.ts"))
searchIdMapFiles.push(path.join(projectRoot,"languages/idMap.ts"))
searchIdMapFiles.push(path.join(projectRoot,"idMap.ts"))
let idMapFile
for( idMapFile of searchIdMapFiles){
// 如果不存在idMap文件则尝试从location/languages/中导入

View File

@ -3,6 +3,7 @@
"version": "1.0.19",
"description": "Vite插件,提供自动插入翻译函数和文本映射等功能",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"release": "pnpm autopublish"
@ -12,5 +13,8 @@
"dependencies": {
"@voerkai18n/utils": "workspace:latest"
},
"lastPublish": "2023-01-12T13:54:31+08:00"
"lastPublish": "2023-01-12T13:54:31+08:00",
"devDependencies": {
"vite": "^4.0.4"
}
}

View File

@ -0,0 +1,32 @@
export {}
import type { VoerkaI18nSupportedLanguages, VoerkaI18nTranslate } from "@Voerkai18n/runtime"
import type { InjectionKey,Plugin } from "vue"
export const defaultPlugin:Plugin
export default defaultPlugin
export type useVoerkaI18n = ()=>{
language:string
defaultLanguage:string, // 默认语言
languages:VoerkaI18nSupportedLanguages
}
export interface VoerkaI18nProviderType{
activeLanguage:string
defaultLanguage:string // 默认语言
languages:VoerkaI18nSupportedLanguages
}
export type VoerkaI18nProvider = InjectionKey<VoerkaI18nProviderType>
export function injectVoerkaI18n():VoerkaI18nProviderType
declare module 'vue' {
interface ComponentCustomProps {
}
interface ComponentCustomProperties {
$activeLanguage:string
t: VoerkaI18nTranslate
}
}

View File

@ -11,39 +11,44 @@
*/
import { computed,reactive,ref } from "vue"
import { computed,reactive,ref,inject} from "vue"
function forceUpdate(app){
function updateComponent(inst){
if(!inst) return
if(inst.update) inst.update()
if(inst.subTree){
if(inst.subTree.children){
inst.subTree.children.forEach( vnode=>{
if(vnode && vnode.component) updateComponent(vnode.component)
})
}
if(inst.subTree.dynamicChildren){
inst.subTree.dynamicChildren.forEach( vnode=>{
if(vnode && vnode.component) updateComponent(vnode.component)
})
}
}
}
try{
updateComponent(app._instance.root)
}catch(e){
console.warn("forceUpdate error: ",e.message)
}
export const VoerkaI18nProvider = Symbol('VoerkaI18nProvider')
const defaultInject ={
activeLanguage:"",
languages:[],
defaultLanguage:""
}
export function injectVoerkaI18n(){
return inject(VoerkaI18nProvider,defaultInject)
}
export function useVoerkaI18n(){
let activeLanguage = ref(VoerkaI18n.activeLanguage)
VoerkaI18n.on((newLanguage)=>{
activeLanguage.value = newLanguage
})
return {
t:VoerkaI18n.t
}
}
export default {
install: (app, opts={}) => {
let options = Object.assign({
i18nScope:null, // 当前作用域实例
forceUpdate:true, // 当语言切换时是否强制重新渲染
}, opts)
let i18nScope = options.i18nScope
if(i18nScope===null){
console.warn("@voerkai18n/vue: i18nScope is not provided, use default i18nScope")
@ -53,30 +58,40 @@ export default {
// 插件只需要安装一次实例
if(app.voerkai18n){
return
}
let activeLanguage = ref(i18nScope.global.activeLanguage)
// 当语言包发生变化时,强制重新渲染组件树
i18nScope.global.on((newLanguage)=>{
app._instance.update()
activeLanguage.value = newLanguage
})
}
app.voerkai18n = i18nScope.global
// 全局i18n对象
app.voerkai18n = options.i18nScope.global
app.provide('i18n', reactive({
let activeLanguage = ref(i18nScope.global.activeLanguage)
app.mixin({
computed:{
$activeLanguage:{
get: () =>activeLanguage.value,
set: (value) =>i18nScope.change(value).then((newLanguage)=>activeLanguage.value=newLanguage)
}
}
})
// 注入一个全局可用的t方法
app.config.globalProperties.t = function(...args){
// 通过访问计算属性activeLanguage来实现当activeLanguage变更时的重新渲染
// 有没有更好的办法?
this.$activeLanguage
return i18nScope.t(...args)
}
app.provide(VoerkaI18nProvider, reactive({
activeLanguage: computed({
get: () => activeLanguage,
set: (value) => i18nScope.global.change(value).then(()=>{
if(options.forceUpdate){
//app._instance.update()
forceUpdate(app)
}
activeLanguage.value = value
})
}),
languages:i18nScope.global.languages,
defaultLanguage:i18nScope.global.defaultLanguage,
}))
}
}

View File

@ -3,11 +3,16 @@
"version": "1.0.12",
"description": "Vue3插件,提供自动插件翻译函数和语言切换功能",
"main": "index.js",
"typings": "index.d.ts",
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"release": "pnpm autopublish"
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@voerkai18n/runtime": "workspace:^1.1.16",
"vue": "latest"
},
"lastPublish": "2023-01-12T13:54:39+08:00"
}

690
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
"sourceMap": true,
"baseUrl": "./",
"strict": true,
"allowJs": true,
"paths": {
"@/*": ["src/*"],
"@@/*": ["src/.umi/*"]