i18n locale messages management tool / library for vue-i18n
v2.x or later
is for vue-i18n-next (Vue 3.x)
If you want to use for vue-i18n@v8.x (Vue 2.x), use the v1.x
The big motivation is as follows.
eslint-plugin-vue-i18n
need it!)i18n-ally
and etc ...)npm install --save-dev vue-i18n-locale-message
If you can globally use CLI only, you need -g
option the below command.
npm install -g vue-i18n-locale-message
yarn add -D vue-i18n-locale-message
If you can globally use CLI, you need global
option the below command.
yarn global add vue-i18n-locale-message
i18n
custom blocki18n
custom blocki18n
custom blocki18n
custom blockconst fs = require('fs')
const { squeeze, infuse } = require('vue-i18n-locale-message')
// read single-file component contents
// NOTE: about scheme of target contents, see the `SFCInfo` type at `types/index.d.ts
const files = [
{
path: '/path/to/src/components/Modal.vue',
content: `<template>
...
<i18n>
{
...
}
<i18n>`
},
// ...
]
// squeeze meta locale message from single-file components
// NOTE: about scheme of meta locale message, see the `MetaLocaleMessage` type at `types/index.d.ts`
const meta = squeeze('/path/to/src', files)
// write squeezed meta locale messages
fs.writeFileSync('/path/to/src/meta.json', JSON.stringify(meta))
// after update meta locale message with 3rd vendor tools or your code, it read meta locale messsage
const updatedMeta = require('/path/to/src/updated-meta.json')
// infuse meta locale message to single-file components
const updatedFiles = infuse('/path/to/src', files, updatedMeta)
// write updated single-file component
updateFiles.forEach(file => {
fs.writeFileSync(file.path, file.content)
})
vue-i18n-locale-message squeeze --target=./src --output=./messages.json
vue-i18n-locale-message infuse --target=./src --locales=./translated.json
vue-i18n-locale-message push --provider=l10n-service-provider \
--conf=110n-service-provider-conf.json \
--target-paths=./src/locales/*.json \
--filename-match=^([\\w]*)\\.json
vue-i18n-locale-message pull --provider=l10n-service-provider \
--conf=110n-service-provider-conf.json \
--output=./src/locales
vue-i18n-locale-message diff --provider=l10n-service-provider \
--conf=110n-service-provider-conf.json \
--target-paths=./src/locales/*.json \
--filename-match=^([\\w]*)\\.json
vue-i18n-locale-message status --provider=l10n-service-provider \
--conf=110n-service-provider-conf.json
$ vue-i18n-locale-message import --provider=l10n-service-provider \
--conf ./l10n-service-provider-conf.json \
--target=./src/locales/ja.json \
--format=json
$ vue-i18n-locale-message export --provider=l10n-service-provider \
--conf ./l10n-service-provider-conf.json \
--output=./src/locales
vue-i18n-locale-message list --locale=en \
--target-paths=./src/locales/*.json \
--filename-match=^([\\w]*)\\.json
Codes | Description |
---|---|
4 | Not completed localization |
5 | There are undefined fields in locale messages |
64 | difference between local and localization services |
{string} basePath
: The base path that single-file components are located in project{SFCFileInfo[]} files
: The target single-file components informationMetaLocaleMessage
Squeeze the meta of locale messages from i18n custom block at single-file components.
In about structure of the meta information that is returned with this function, You can see the here.
{string} basePath
: The base path that single-file components are located in project{SFCFileInfo[]} sources
: The target single-file components information{MetaLocaleMessage}
: The meta of locale messageSFCFileInfo[]
Infuse the meta of locale messages to i18n custom block at single-file components.
infuse
function will return new single-file components information that is updated with the single-file components information specified as sources
and the meta of locale message as meta
.
provider
: The target localization service provider, required, same provider
option of status
commandconf
: The json file configration of localization service provider, same conf
option of status
commandlocales
: For some locales of translation status, same locales
option of status
commandPromise<TranslationStatus[]>
You can use the push
or pull
commands to push the locale message to the localization service as a resource for that service, and also to pull resources from the l10n service as the locale message.
When you run the following commands,
push
pull
diff
status
import
export
you need the provider that implements the following.
push
methodpull
methodstatus
methodimport
methodexport
methodThe type definition with TypeScript is as follows:
/**
* Provider factory function
*/
type ProviderFactory<T = {}> = (configration: ProviderConfiguration<T>) => Provider
/**
* Translation Status
*/
export type TranslationStatus = {
locale: Locale // target locale
percentage: number // translation percentage
}
/**
* Raw Locale Message
*/
export type RawLocaleMessage = {
locale: Locale // target locale
format: string // locale message format
data: Buffer // data of locale message
}
/**
* Provider interface
*/
interface Provider {
/**
* push the locale messsages to localization service
*/
push (args: PushArguments): Promise<void>
/**
* pull the locale messages from localization service
*/
pull (args: PullArguments): Promise<LocaleMessages>
/**
* indicate translation status from localization service
*/
status (args: StatusArguments): Promise<TranslationStatus[]>
/**
* import the locale messsages to localization service
*/
import (args: ImportArguments): Promise<void>
/**
* export the locale message buffer from localization service
*/
export (args: ExportArguments): Promise<RawLocaleMessage[]>
}
type CommonArguments = {
dryRun: boolean // whether the CLI run as dryRun mode
normalize?: string // normalization ways for locale messages or resource
}
/**
* Provider Push Arguments
*/
type PushArguments = {
messages: LocaleMessages // the locale messages that push to localization service
} & CommonArguments
/**
* Provider Pull Arguments
*/
type PullArguments = {
locales: Locale[] // locales that pull from localization service, if empty, you must pull the all locale messages
} & CommonArguments
/**
* Provider Status Arguments
*/
export type StatusArguments = {
locales: Locale[] // locales that indicate translation status from localization service, if empty, you must indicate translation status all locales
}
/**
* Provider Import Arguments
*/
export type ImportArguments = {
messages: RawLocaleMessage[] // the raw locale messages that import to localization service
} & CommonArguments
/**
* Provider Export Arguments
*/
export type ExportArguments = {
locales: Locale[] // locales that export from localization service, if empty, you must export all locale messages
format: string // locale messages format
} & CommonArguments
/**
* ProviderConfiguration provider fields structure
* e.g.
* {
* "provider": {
* "token": "xxx"
* }
* }
*/
interface ProviderConfiguration<T = {}> {
provider: { [key in keyof ProviderConfigurationValue<T>]: ProviderConfigurationValue<T>[key] }
}
type ProviderConfigurationValue<T = {}> = T & { [prop: string]: unknown }
As an implementation example of Provider, there is poeditor-service-provider
implemented as localization service provider of poeditor.
The structure of locale messages to be squeezed is layered with the directory structure and single-file component (.vue
) filename.
This repotitory demo
project directory structure:
cd demo
tree src
src
├── App.vue
├── components
│ ├── Modal.vue
│ └── nest
│ └── RankingTable.vue
├── i18n.js
├── locales
│ ├── en.json
│ └── ja.json
├── main.js
└── pages
└── Login.vue
4 directories, 8 files
You use vue-cli-locale-message
CLI, run squeeze
command as follows:
vue-i18n-locale-message squeeze --target=./src --output=./messages.json
cat ./messages.json
You will get the following JSON structure (the following output results are commented To make it easier to understand):
{
"ja": { // for `ja` locale`
"App": { // src/App.vue
"title": "アプリケーション",
"lang": "言語切り替え"
},
"components": { // src/components
"Modal": { // src/components/Modal.vue
"ok": "OK",
"cancel": "キャンセル"
}
},
"pages": { // src/pages
"Login": { // src/pages/Login.vue
"id": "ユーザーID",
"password": "パスワード",
"confirm": "パスワードの確認入力",
"button": "ログイン"
}
}
},
"en": { // for `en` locale
"App": { // src/App.vue
"title": "Application",
"lang": "Change languages"
},
"components": { // src/components
"Modal": { // src/components/Modal.vue
"ok": "OK",
"cancel": "Cancel"
},
"nest": { // src/components/nest
"RankingTable": { // src/components/nest/RankingTable.vue
"headers": {
"rank": "Rank",
"name": "Name",
"score": "Score"
}
}
}
}
}
}
Details changes for each release are documented in the CHANGELOG.md.
Please make sure to read the Issue Reporting Checklist before opening an issue. Issues not conforming to the guidelines may be closed immediately.
Managed with GitHub Projects