feat: plugin-locale 添加新功能

1. 支持 legacy 配置
2. 支持 share 配置
3. 支持 baseNavigator 配置
4. 添加setLocale方法
5. 添加addLocale方法
6. 添加getAllLocales方法
This commit is contained in:
万纯 2021-01-14 19:09:59 +08:00
parent b5e2a8426e
commit e43ea5e56c
9 changed files with 122 additions and 53 deletions

View File

@ -23,7 +23,6 @@ export default (api) => {
const absRuntimeFilePath = join(namespace, 'runtime.js');
const generatedOnce = false;
api.onGenerateFiles(() => {
// 文件写出
const { roles = {} } = api.config.access || {};

View File

@ -10,14 +10,18 @@ export default (api) => {
} = api;
api.describe({
key: 'locale',
config: {
schema(joi) {
return joi.object();
},
default: {}
default: {},
onChange: api.ConfigChangeType.regenerateTmpFiles
}
});
api.addRuntimePluginKey(() => 'locale');
const absoluteFilePath = join(namespace, 'core.js');
const absRuntimeFilePath = join(namespace, 'runtime.js');
@ -30,12 +34,18 @@ export default (api) => {
api.addTmpGenerateWatcherPaths(getLocaleFileBasePath);
api.onGenerateFiles(() => {
// .fes配置
const userConfig = {
locale: 'zh-CN', // default locale
fallbackLocale: 'zh-CN', // set fallback locale
legacy: true,
baseNavigator: true, // 开启浏览器语言检测
share: true, // 用户是否需要手动改变语言
...api.config.locale
};
const loacleConfigFileBasePath = getLocaleFileBasePath();
// 文件写出
const defaultOptions = api.config.locale || {};
const locales = getLocalesJSON(loacleConfigFileBasePath);
api.writeTmpFile({
@ -44,19 +54,17 @@ export default (api) => {
readFileSync(join(__dirname, 'runtime/core.tpl'), 'utf-8'),
{
REPLACE_LOCALES: locales,
REPLACE_DEFAULT_OPTIONS: JSON.stringify(defaultOptions)
REPLACE_DEFAULT_OPTIONS: JSON.stringify({
locale: userConfig.locale,
fallbackLocale: userConfig.fallbackLocale,
legacy: userConfig.legacy
}, null, 2),
BASE_NAVIGATOR: userConfig.baseNavigator,
SHARE: userConfig.share
}
)
});
api.writeTmpFile({
path: absRuntimeFilePath,
content: readFileSync(
join(__dirname, 'runtime/runtime.tpl'),
'utf-8'
)
});
api.copyTmpFiles({
namespace,
path: join(__dirname, 'runtime'),
@ -66,12 +74,10 @@ export default (api) => {
api.addPluginExports(() => [
{
specifiers: ['useI18n', 'setLocale'],
specifiers: ['useI18n', 'locale'],
source: absoluteFilePath
}
]);
api.addRuntimePluginKey(() => 'onLocaleReady');
api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`);
};

View File

@ -5,13 +5,38 @@
// locales目录下以语言简称为子文件下存放配置信息
// 其他插件可以运行时修改配置
// 所有插件使用一个语言和配置
import { createI18n, useI18n } from 'vue-i18n/dist/vue-i18n.esm-bundler.js';
import { isRef } from 'vue';
import { createI18n, useI18n } from 'vue-i18n/dist/vue-i18n.esm-bundler.js';
import { plugin, ApplyPluginsType } from "@@/core/coreExports";
import SelectLang from "./views/SelectLang"
import SelectLang from "./views/SelectLang";
{{ #SHARE }}
// 共享出去
plugin.share("locale", { SelectLang });
{{ /SHARE }}
const locales = {{{REPLACE_LOCALES}}};
const defaultOptions = {{{REPLACE_DEFAULT_OPTIONS}}}
const defaultOptions = {{{REPLACE_DEFAULT_OPTIONS}}};
const BASE_NAVIGATOR = {{{BASE_NAVIGATOR}}};
const getDefaultLocale = () => {
const fes_locale = window.localStorage.getItem("fes_locale");
if (fes_locale) {
return {
locale: fes_locale,
fallbackLocale: fes_locale,
};
}
if (BASE_NAVIGATOR) {
return {
locale: window.navigator.language,
fallbackLocale: window.navigator.language,
};
}
return {};
};
const messages = {};
if (Array.isArray(locales)) {
@ -20,21 +45,53 @@ if (Array.isArray(locales)) {
});
}
const i18n = createI18n({ ...defaultOptions, messages });
const i18n = createI18n({
...defaultOptions,
...getDefaultLocale(),
messages,
});
// 共享出去
plugin.share("locale", { i18n, SelectLang });
const setLocale = (locale)=>{
i18n.global.locale = locale
window.localStorage.setItem("fes_locale", i18n.global.locale);
const setLocale = ({ lang }) => {
if (isRef(i18n.global.locale)) {
i18n.global.locale.value = lang;
} else {
i18n.global.locale = lang;
}
window.localStorage.setItem("fes_locale", lang);
};
const addLocale = (locale, messages)=>{};
const addLocale = ({ lang, messages }) => {
messages[lang] = messages;
if (isRef(i18n.global.messages)) {
i18n.global.messages.value[lang] = messages;
} else {
i18n.global.messages[lang] = messages;
}
};
const getAllLocales = ()=>{};
const getAllLocales = () => {
return Object.keys(
isRef(i18n.global.messages)
? i18n.global.messages.value
: i18n.global.messages
).sort();
};
const install = (app)=>{
const install = (app) => {
const runtimeConfig = plugin.applyPlugins({
key: "locale",
type: ApplyPluginsType.modify,
initialValue: {},
});
app.use(i18n);
}
};
export { useI18n, setLocale, install }
const locale = {
setLocale,
addLocale,
getAllLocales,
messages,
};
export { useI18n, locale, install };

View File

@ -0,0 +1,5 @@
import { install } from './core';
export function onAppCreated({ app }) {
install(app);
}

View File

@ -1,5 +0,0 @@
import { install } from "./core";
export function onAppCreated({ app }) {
install(app)
}

View File

@ -4,7 +4,7 @@
<template #overlay>
<a-menu :selectedKeys="selectedKeys" @click="handleClick">
<a-menu-item
v-for="(item) in configs"
v-for="item in configs"
:key="item.lang"
class="lang-item"
>
@ -23,7 +23,7 @@ import 'ant-design-vue/lib/dropdown/style';
import 'ant-design-vue/lib/menu/style';
import { GlobalOutlined } from '@ant-design/icons-vue';
import { useI18n } from 'vue-i18n/dist/vue-i18n.esm-bundler';
import { reactive, computed } from 'vue';
import { computed } from 'vue';
import langUConfigMap from '../langUConfigMap';
export default {
@ -34,14 +34,20 @@ export default {
GlobalOutlined
},
setup() {
const { availableLocales, locale } = useI18n();
const { messages, locale } = useI18n();
const selectedKeys = computed(() => [locale.value]);
const configs = reactive([]);
availableLocales.forEach((item) => {
configs.push(langUConfigMap[item] || {});
const configs = computed(() => {
const arr = [];
Object.keys(messages.value)
.sort()
.forEach((item) => {
arr.push(langUConfigMap[item] || {});
});
return arr;
});
const handleClick = ({ key }) => {
locale.value = key;
window.localStorage.setItem('fes_locale', key);
};
return {
handleClick,

View File

@ -23,9 +23,9 @@ export function getLocales(cwd) {
export function getLocalesJSON(cwd) {
const locales = getLocales(cwd);
return JSON.stringify(locales)
return JSON.stringify(locales, null, 2)
.replace(
/"message":("(.+?)")/g,
/"message": ("(.+?)")/g,
(global, m1, m2) => `"message": ${m2.replace(/\^/g, '"')}`
)
.replace(/\\r\\n/g, '\r\n')

View File

@ -22,6 +22,9 @@ export default {
name: 'onepiece'
}]
},
locale: {
legacy: true
},
devServer: {
port: 8080
}

View File

@ -16,21 +16,22 @@
<script>
import { ref, onMounted } from 'vue';
import {
access, useAccess, useRouter, useI18n, setLocale
access, useAccess, useRouter, useI18n, locale
} from '@webank/fes';
export default {
setup() {
const fes = ref('fes upgrade to vue3');
const accessOnepicess = useAccess('/onepiece1');
const { t } = useI18n();
const localI18n = useI18n();
const router = useRouter();
const accessId = ref('/onepiece1');
onMounted(() => {
console.log(router);
console.log('mounted1!!');
setTimeout(() => {
setLocale('en-US');
locale.setLocale({ lang: 'en-US' });
locale.addLocale({ lang: 'ja-JP', messages: { test: 'テスト' } });
console.log(locale.getAllLocales());
access.addAccess('/onepiece1');
}, 2000);
setTimeout(() => {
@ -38,14 +39,11 @@ export default {
}, 4000);
// router.push('/onepiece');
});
onMounted(() => {
console.log('mounted2!!');
});
return {
accessId,
fes,
accessOnepicess,
t
t: localI18n.t
};
}
};