1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Merge pull request #3763 from MetaMask/i18n-helper

I18n - Improve verify locales utility
This commit is contained in:
kumavis 2018-04-02 13:09:59 -07:00 committed by GitHub
commit f6f144643f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 92 additions and 136 deletions

View File

@ -232,7 +232,7 @@
"done": { "done": {
"message": "Fertig" "message": "Fertig"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "Statelogs herunterladen" "message": "Statelogs herunterladen"
}, },
"dropped": { "dropped": {

View File

@ -247,7 +247,7 @@
"done": { "done": {
"message": "Completo" "message": "Completo"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "Descargar logs de estado" "message": "Descargar logs de estado"
}, },
"dropped": { "dropped": {

View File

@ -223,7 +223,7 @@
"done": { "done": {
"message": "संपन्न" "message": "संपन्न"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "राज्य लॉग डाउनलोड करें" "message": "राज्य लॉग डाउनलोड करें"
}, },
"edit": { "edit": {

View File

@ -223,7 +223,7 @@
"done": { "done": {
"message": "Gedaan" "message": "Gedaan"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "Staatslogboeken downloaden" "message": "Staatslogboeken downloaden"
}, },
"edit": { "edit": {

View File

@ -235,9 +235,8 @@
"done": { "done": {
"message": "Готово" "message": "Готово"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "Скачать журнал состояния" "message": "Скачать журнал состояния"
},
"dropped": { "dropped": {
"message": "Отброшена" "message": "Отброшена"
}, },

View File

@ -223,7 +223,7 @@
"done": { "done": {
"message": "Končano" "message": "Končano"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "Prenesi state dnevnike" "message": "Prenesi state dnevnike"
}, },
"edit": { "edit": {

View File

@ -223,7 +223,7 @@
"done": { "done": {
"message": "เสร็จสิ้น" "message": "เสร็จสิ้น"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "ดาวน์โหลดล็อกสถานะ" "message": "ดาวน์โหลดล็อกสถานะ"
}, },
"edit": { "edit": {

View File

@ -235,7 +235,7 @@
"done": { "done": {
"message": "完成" "message": "完成"
}, },
"downloadStatelogs": { "downloadStateLogs": {
"message": "下載狀態紀錄" "message": "下載狀態紀錄"
}, },
"dropped": { "dropped": {

View File

@ -10,87 +10,88 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var fs = require('fs') const fs = require('fs')
var path = require('path') const path = require('path')
const localeIndex = require('../app/_locales/index.json')
console.log('Locale Verification') console.log('Locale Verification')
var locale = process.argv[2] const specifiedLocale = process.argv[2]
if (!locale || locale == '') { if (specifiedLocale) {
console.log('Must enter a locale as argument. exitting') console.log(`Verifying selected locale "${specifiedLocale}":\n\n`)
process.exit(1) const locale = localeIndex.find(localeMeta => localeMeta.code === specifiedLocale)
} verifyLocale({ localeMeta })
console.log("verifying for locale " + locale)
localeFilePath = path.join(process.cwd(), 'app', '_locales', locale, 'messages.json')
try {
localeObj = JSON.parse(fs.readFileSync(localeFilePath, 'utf8'));
} catch (e) {
if(e.code == 'ENOENT') {
console.log('Locale file not found')
} else {
console.log('Error opening your locale file: ', e)
}
process.exit(1)
}
englishFilePath = path.join(process.cwd(), 'app', '_locales', 'en', 'messages.json')
try {
englishObj = JSON.parse(fs.readFileSync(englishFilePath, 'utf8'));
} catch (e) {
if(e.code == 'ENOENT') {
console.log("English File not found")
} else {
console.log("Error opening english locale file: ", e)
}
process.exit(1)
}
console.log('\tverifying whether all your locale strings are contained in the english one')
var counter = 0
var foundErrorA = false
var notFound = [];
Object.keys(localeObj).forEach(function(key){
if (!englishObj[key]) {
foundErrorA = true
notFound.push(key)
}
counter++
})
if (foundErrorA) {
console.log('\nThe following string(s) is(are) not found in the english locale:')
notFound.forEach(function(key) {
console.log(key)
})
} else { } else {
console.log('\tall ' + counter +' strings declared in your locale were found in the english one') console.log('Verifying all locales:\n\n')
} localeIndex.forEach(localeMeta => {
verifyLocale({ localeMeta })
console.log('\n\tverifying whether your locale contains all english strings') console.log('\n')
var counter = 0
var foundErrorB = false
var notFound = [];
Object.keys(englishObj).forEach(function(key){
if (!localeObj[key]) {
foundErrorB = true
notFound.push(key)
}
counter++
})
if (foundErrorB) {
console.log('\nThe following string(s) is(are) not found in the your locale:')
notFound.forEach(function(key) {
console.log(key)
}) })
} else {
console.log('\tall ' + counter +' english strings were found in your locale!')
} }
if (!foundErrorA && !foundErrorB) {
console.log('You are good to go')
} function verifyLocale({ localeMeta }) {
const localeCode = localeMeta.code
const localeName = localeMeta.name
try {
const localeFilePath = path.join(process.cwd(), 'app', '_locales', localeCode, 'messages.json')
targetLocale = JSON.parse(fs.readFileSync(localeFilePath, 'utf8'));
} catch (e) {
if (e.code == 'ENOENT') {
console.log('Locale file not found')
} else {
console.log(`Error opening your locale ("${localeCode}") file: `, e)
}
process.exit(1)
}
try {
const englishFilePath = path.join(process.cwd(), 'app', '_locales', 'en', 'messages.json')
englishLocale = JSON.parse(fs.readFileSync(englishFilePath, 'utf8'));
} catch (e) {
if(e.code == 'ENOENT') {
console.log('English File not found')
} else {
console.log('Error opening english locale file: ', e)
}
process.exit(1)
}
// console.log(' verifying whether all your locale ("${localeCode}") strings are contained in the english one')
const extraItems = compareLocalesForMissingItems({ base: targetLocale, subject: englishLocale })
// console.log('\n verifying whether your locale ("${localeCode}") contains all english strings')
const missingItems = compareLocalesForMissingItems({ base: englishLocale, subject: targetLocale })
const englishEntryCount = Object.keys(englishLocale).length
const coveragePercent = 100 * (englishEntryCount - missingItems.length) / englishEntryCount
console.log(`Status of **${localeName} (${localeCode})** ${coveragePercent.toFixed(2)}% coverage:`)
if (extraItems.length) {
console.log('\nMissing from english locale:')
extraItems.forEach(function(key) {
console.log(` - [ ] ${key}`)
})
} else {
// console.log(` all ${counter} strings declared in your locale ("${localeCode}") were found in the english one`)
}
if (missingItems.length) {
console.log(`\nMissing:`)
missingItems.forEach(function(key) {
console.log(` - [ ] ${key}`)
})
} else {
// console.log(` all ${counter} english strings were found in your locale ("${localeCode}")!`)
}
if (!extraItems.length && !missingItems.length) {
console.log('Full coverage : )')
}
}
function compareLocalesForMissingItems({ base, subject }) {
return Object.keys(base).filter((key) => !subject[key])
}

View File

@ -6,9 +6,12 @@ The MetaMask browser extension supports new translations added in the form of ne
## Adding a new Language ## Adding a new Language
Each supported language is represented by a folder in `app/_locales` whose name is that language's subtag ([look up a language subtag using this tool](https://r12a.github.io/app-subtags/)). - Each supported language is represented by a folder in `app/_locales` whose name is that language's subtag (example: `app/_locales/es/`). (look up a language subtag using the [r12a "Find" tool](https://r12a.github.io/app-subtags/) or this [wikipedia list](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)).
- Inside that folder there should be a `messages.json`.
- An easy way to start your translation is to first **make a copy** of `app/_locales/en/messages.json` (the english translation), and then **translate the `message` key** for each in-app message.
- **The `description` key** is just to add context for what the translation is about, it **does not need to be translated**.
- Add the language to the [locales index](https://github.com/MetaMask/metamask-extension/blob/master/app/_locales/index.json) `app/_locales/index.json`
Inside that folder there should be a `messages.json` file that follows the specified format. An easy way to start your translation is to first duplicate `app/_locales/en/messages.json` (the english translation), and then update the `message` key for each in-app message.
That's it! When MetaMask is loaded on a computer with that language set as the system language, they will see your translation instead of the default one. That's it! When MetaMask is loaded on a computer with that language set as the system language, they will see your translation instead of the default one.
@ -20,7 +23,7 @@ To automatically see if you are missing any phrases to translate, we have a scri
node development/verify-locale-strings.js $YOUR_LOCALE node development/verify-locale-strings.js $YOUR_LOCALE
``` ```
Where `$YOUR_LOCALE` is your [locale string](https://r12a.github.io/app-subtags/), i.e. the name of your language folder. Where `$YOUR_LOCALE` is your locale string (example: `es`), i.e. the name of your language folder.
To verify that your translation works in the app, you will need to [build a local copy](https://github.com/MetaMask/metamask-extension#building-locally) of MetaMask. You will need to change your browser language, your operating system language, and restart your browser (sorry it's so much work!). To verify that your translation works in the app, you will need to [build a local copy](https://github.com/MetaMask/metamask-extension#building-locally) of MetaMask. You will need to change your browser language, your operating system language, and restart your browser (sorry it's so much work!).

47
package-lock.json generated
View File

@ -7148,12 +7148,6 @@
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
}, },
"fork-stream": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz",
"integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=",
"dev": true
},
"form-data": { "form-data": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
@ -8683,17 +8677,6 @@
"gulp-util": "3.0.8" "gulp-util": "3.0.8"
} }
}, },
"gulp-if": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz",
"integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=",
"dev": true,
"requires": {
"gulp-match": "1.0.3",
"ternary-stream": "2.0.1",
"through2": "2.0.3"
}
},
"gulp-json-editor": { "gulp-json-editor": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz", "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz",
@ -8845,15 +8828,6 @@
} }
} }
}, },
"gulp-match": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz",
"integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=",
"dev": true,
"requires": {
"minimatch": "3.0.4"
}
},
"gulp-replace": { "gulp-replace": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.6.1.tgz", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.6.1.tgz",
@ -13247,15 +13221,6 @@
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
}, },
"merge-stream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
"integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
"dev": true,
"requires": {
"readable-stream": "2.3.3"
}
},
"merkle-patricia-tree": { "merkle-patricia-tree": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.0.tgz", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.0.tgz",
@ -20753,18 +20718,6 @@
"inherits": "2.0.3" "inherits": "2.0.3"
} }
}, },
"ternary-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz",
"integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=",
"dev": true,
"requires": {
"duplexify": "3.5.1",
"fork-stream": "0.0.4",
"merge-stream": "1.0.1",
"through2": "2.0.3"
}
},
"testem": { "testem": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/testem/-/testem-2.0.0.tgz", "resolved": "https://registry.npmjs.org/testem/-/testem-2.0.0.tgz",