* refactor: replace translation scripts and ui with vitepress-translation-helper
* chore: remove old translation scripts
* chore: bump vitepress-translation-helper
* chore: bump vitepress-translation-helper
* Update index.ts
---------
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com>
1. Create the corresponding `<lang>` sub-folder for your translation.
2. Modify the i18n configuration in the `.vitepress` sub-folder.
3. Translate the docs and run the doc site to self-test locally.
-4. Create a checkpoint for your language by running `pnpm run docs:translation-status <lang> [<commit>]`. A checkpoint is the hash and date of the latest commit when you do the translation. The checkpoint information is stored in the status file `packages/docs/.vitepress/translation-status.json`. _It's crucial for long-term maintenance since all the further translation sync-ups are based on their previous checkpoints._ Usually, you can skip the commit argument because the default value is `main`.
+4. Create a checkpoint for your language by running `pnpm run docs:translation:update <lang> [<commit>]`. A checkpoint is the hash and date of the latest commit when you do the translation. The checkpoint information is stored in the status file `packages/docs/.vitepress/translation-status.json`. _It's crucial for long-term maintenance since all the further translation sync-ups are based on their previous checkpoints._ Usually, you can skip the commit argument because the default value is `main`.
5. Commit all the changes and create a pull request to our GitHub repo.
We will have a paragraph at the top of each translation page that shows the translation status. That way, users can quickly determine if the translation is up-to-date or lags behind the English version.
1. See what translation you need to sync up with the original docs. There are two popular ways:
1. Via the [GitHub Compare](https://github.com/vuejs/router/compare/) page, only see the changes in `packages/docs/*` from the checkpoint hash to `main` branch. You can find the checkpoint hash for your language via the translation status file `packages/docs/.vitepress/translation-status.json`. The compare page can be directly opened with the hash as part of the URL, e.g. https://github.com/vuejs/router/compare/e008551...main
- 2. Via a local command: `pnpm run docs:compare-to-translate <lang> [<commit>]`.
+ 2. Via a local command: `pnpm run docs:translation:compare <lang> [<commit>]`.
2. Create your own branch and start the translation update, following the previous comparison.
-3. Create a checkpoint for your language by running `pnpm run docs:translation-status <lang> [<commit>]`.
+3. Create a checkpoint for your language by running `pnpm run docs:translation:update <lang> [<commit>]`.
4. Commit all the changes and create a pull request to our GitHub repo.
<!-- TODO: add an example once we have got one -->
- Ensure you maintain the _checkpoint_ properly. Also, ensure the _translation status_ is well-displayed on the top of each translation page.
- Utilize the diff result between the latest official repository and your own checkpoint to guide your translation.
-Tip: you can add the official repo as a remote to your forked repo. This way, you can still run `pnpm run docs:translation-status <lang> [<commit>]` and `npm run docs:compare-to-translate <lang> [<commit>]` to get the checkpoint and diff result:
+Tip: you can add the official repo as a remote to your forked repo. This way, you can still run `pnpm run docs:translation:update <lang> [<commit>]` and `npm run docs:translation:compare <lang> [<commit>]` to get the checkpoint and diff result:
```bash
# prepare the upstream remote
git fetch upstream main
# set the checkpoint
-pnpm run docs:translation-status <lang> upstream/main
+pnpm run docs:translation:update <lang> upstream/main
# get the diff result
-pnpm run docs:compare-to-translate <lang> upstream/main
+pnpm run docs:translation:compare <lang> upstream/main
```
<!-- TODO: add an example once we have got one -->
"build:dts": "pnpm run -r build:dts",
"docs": "pnpm run --filter ./packages/docs -r docs",
"docs:api": "pnpm run --filter ./packages/docs -r docs:api",
- "docs:compare-to-translate": "pnpm run --filter ./packages/docs -r docs:compare-to-translate",
- "docs:translation-status": "pnpm run --filter ./packages/docs -r docs:translation-status",
+ "docs:translation:compare": "pnpm run --filter ./packages/docs -r docs:translation:compare",
+ "docs:translation:update": "pnpm run --filter ./packages/docs -r docs:translation:update",
+ "docs:translation:status": "pnpm run --filter ./packages/docs -r docs:translation:status",
"docs:build": "pnpm run docs:api && pnpm run --filter ./packages/docs -r docs:build",
"docs:preview": "pnpm run --filter ./packages/docs -r docs:preview",
"play": "pnpm run -r play",
import DefaultTheme from 'vitepress/theme'
import AsideSponsors from './components/AsideSponsors.vue'
// import HomeSponsors from './components/HomeSponsors.vue'
-import TranslationStatus from './components/TranslationStatus.vue'
+import TranslationStatus from 'vitepress-translation-helper/ui/TranslationStatus.vue'
import './styles/vars.css'
import './styles/sponsors.css'
import VueSchoolLink from './components/VueSchoolLink.vue'
import VueMasteryLogoLink from './components/VueMasteryLogoLink.vue'
+import status from '../translation-status.json'
+
+const i18nLabels = {
+ zh: '该翻译已同步到了 ${date} 的版本,其对应的 commit hash 是 <code>${hash}</code>。',
+}
const theme: Theme = {
...DefaultTheme,
return h(DefaultTheme.Layout, null, {
// 'home-features-after': () => h(HomeSponsors),
'aside-ads-before': () => h(AsideSponsors),
- 'doc-before': () => h(TranslationStatus),
+ 'doc-before': () => h(TranslationStatus, { status, i18nLabels }),
})
},
+++ /dev/null
-// @ts-check
-import { readFile } from 'fs/promises'
-import simpleGit from 'simple-git'
-
-// The path to the translation status file.
-const STATUS_FILE_PATH = './.vitepress/translation-status.json'
-
-const usage = `
-Usage: pnpm run docs:compare-to-translate <locale> [<commit>]
- locale: The target locale to compare.
- commit: The target commit to compare. It could be a branch, a tag, or a hash. Default to 'main'.`
-
-async function getLocaleHash (lang) {
- try {
- const content = await readFile(STATUS_FILE_PATH, 'utf8')
- const data = JSON.parse(content)
- return data[lang]?.hash
- } catch (err) {
- console.log('No previous status file. Will create a new one.')
- }
-}
-
-async function main() {
- if (process.argv.find(arg => arg === '--help' || arg === '-h')) {
- console.log(usage)
- return
- }
-
- const locale = process.argv[2]
- const commit = process.argv[3] || 'main'
-
- const hash = await getLocaleHash(locale)
- if (hash) {
- console.log(`The last checkpoint of docs(${locale}) is "${hash}".\n`)
- const git = simpleGit()
- const result = await git.diff([`${hash}..${commit}`, '.'])
- console.log(result)
- console.log(`\nAfter finishing the translation, you can run\n"pnpm run docs:translation-status ${locale} ${hash}"\nor\n"pnpm run docs:translation-status ${locale}${commit !== 'main' ? ' ' + commit : ''}"\nto update the translation status file.`)
- } else {
- console.log(`No docs(${locale}) checkpoint found.\n`)
- console.log(usage)
- }
-}
-
-main()
+++ /dev/null
-// @ts-check
-import { writeFile, readFile } from 'fs/promises'
-import simpleGit from 'simple-git'
-
-// The path to the translation status file.
-const STATUS_FILE_PATH = './.vitepress/translation-status.json'
-
-const usage = `
-Usage: pnpm run docs:translation-status <locale> [<commit>]
- locale: The target locale to update.
- commit: The target commit to update. It could be a branch, a tag, or a hash. Default to 'main'.`
-
-async function getCommitInfo (commit) {
- try {
- const git = simpleGit()
- const log = await git.log([commit, '-n', '1'])
- const { hash, date } = log.latest
- return { hash, date: new Date(date).toISOString().substring(0, 10) }
- } catch (err) {
- return { hash: '', date: '' }
- }
-}
-
-async function writeLangMap (lang, hash, date) {
- const data = {}
- try {
- const previousContent = await readFile(STATUS_FILE_PATH, 'utf8')
- const previousJson = JSON.parse(previousContent)
- Object.assign(data, previousJson)
- }
- catch (err) {
- console.log('No previous status file. Will create a new one.')
- }
- data[lang] = {
- hash,
- date,
- }
- await writeFile(STATUS_FILE_PATH, JSON.stringify(data, null, 2))
-}
-
-async function main() {
- if (process.argv.find(arg => arg === '--help' || arg === '-h')) {
- console.log(usage)
- return
- }
-
- const locale = process.argv[2]
- const commit = process.argv[3] || 'main'
-
- const { hash, date } = await getCommitInfo(commit)
- if (!hash) {
- console.log(`❌ No commit found for "${commit}".`)
- return
- } else {
- await writeLangMap(locale, hash, date)
- console.log(`✅ Updated ${locale} to "${hash}" (${date})`)
- }
-}
-
-main()
"scripts": {
"docs": "vitepress dev .",
"docs:api": "node run-typedoc.mjs",
- "docs:compare-to-translate": "node compare-to-translate.mjs",
- "docs:translation-status": "node generate-translation-status.mjs",
+ "docs:translation:compare": "v-translation compare",
+ "docs:translation:update": "v-translation update",
+ "docs:translation:status": "v-translation status",
"docs:build": "vitepress build .",
"docs:preview": "vitepress preview ."
},
"dependencies": {
"simple-git": "^3.18.0",
"vitepress": "1.0.0-rc.35",
+ "vitepress-translation-helper": "^0.1.3",
"vue-router": "workspace:*"
}
}
vitepress:
specifier: 1.0.0-rc.35
version: 1.0.0-rc.35(@algolia/client-search@4.19.1)(search-insights@2.7.0)(typescript@5.3.3)
+ vitepress-translation-helper:
+ specifier: ^0.1.3
+ version: 0.1.3(vitepress@1.0.0-rc.35)(vue@3.4.8)
vue-router:
specifier: workspace:*
version: link:../router
source-map-js: 1.0.2
dev: false
+ /@vue/compiler-core@3.4.8:
+ resolution: {integrity: sha512-GjAwOydZV6UyVBi1lYW5v4jjfU6wOeyi3vBATKJOwV7muYF0/nZi4kfdJc0pwdT5lXwbbx57lyA2Y356rFpw1A==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@vue/shared': 3.4.8
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.0.2
+ dev: false
+
/@vue/compiler-dom@3.3.11:
resolution: {integrity: sha512-zoAiUIqSKqAJ81WhfPXYmFGwDRuO+loqLxvXmfUdR5fOitPoUiIeFI9cTTyv9MU5O1+ZZglJVTusWzy+wfk5hw==}
dependencies:
'@vue/shared': 3.4.5
dev: false
+ /@vue/compiler-dom@3.4.8:
+ resolution: {integrity: sha512-GsPyji42zmkSJlaDFKXvwB97ukTlHzlFH/iVzPFYz/APnSzuhu/CMFQbsYmrtsnc2yscF39eC4rKzvKR27aBug==}
+ dependencies:
+ '@vue/compiler-core': 3.4.8
+ '@vue/shared': 3.4.8
+ dev: false
+
/@vue/compiler-sfc@3.3.11:
resolution: {integrity: sha512-U4iqPlHO0KQeK1mrsxCN0vZzw43/lL8POxgpzcJweopmqtoYy9nljJzWDIQS3EfjiYhfdtdk9Gtgz7MRXnz3GA==}
dependencies:
source-map-js: 1.0.2
dev: false
+ /@vue/compiler-sfc@3.4.8:
+ resolution: {integrity: sha512-3ZcurOa6bQdZ6VZLtMqYSUZqpsMqfX0MC3oCxQG0VIJFCqouZAgRYJN1c8QvGs7HW5wW8aXVvUOQU0ILVlYHKA==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@vue/compiler-core': 3.4.8
+ '@vue/compiler-dom': 3.4.8
+ '@vue/compiler-ssr': 3.4.8
+ '@vue/shared': 3.4.8
+ estree-walker: 2.0.2
+ magic-string: 0.30.5
+ postcss: 8.4.32
+ source-map-js: 1.0.2
+ dev: false
+
/@vue/compiler-ssr@3.3.11:
resolution: {integrity: sha512-Zd66ZwMvndxRTgVPdo+muV4Rv9n9DwQ4SSgWWKWkPFebHQfVYRrVjeygmmDmPewsHyznCNvJ2P2d6iOOhdv8Qg==}
dependencies:
'@vue/shared': 3.4.5
dev: false
+ /@vue/compiler-ssr@3.4.8:
+ resolution: {integrity: sha512-nxN79LHeAemhBpIa2PQ6rz57cW7W4C/XIJCOMSn2g49u6q2ekirmJI0osAOTErQPApOR0KwP2QyeTexX4zQCrw==}
+ dependencies:
+ '@vue/compiler-dom': 3.4.8
+ '@vue/shared': 3.4.8
+ dev: false
+
/@vue/devtools-api@6.5.1:
resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
dev: false
'@vue/shared': 3.4.5
dev: false
+ /@vue/reactivity@3.4.8:
+ resolution: {integrity: sha512-UJYMQ3S2rqIGw9IvKomD4Xw2uS5VlcKEEmwcfboGOdrI79oqebxnCgTvXWLMClvg3M5SF0Cyn+9eDQoyGMLu9Q==}
+ dependencies:
+ '@vue/shared': 3.4.8
+ dev: false
+
/@vue/runtime-core@3.3.11:
resolution: {integrity: sha512-g9ztHGwEbS5RyWaOpXuyIVFTschclnwhqEbdy5AwGhYOgc7m/q3NFwr50MirZwTTzX55JY8pSkeib9BX04NIpw==}
dependencies:
'@vue/shared': 3.4.5
dev: false
+ /@vue/runtime-core@3.4.8:
+ resolution: {integrity: sha512-sMRXOy89KnwY6fWG5epgPOsCWzpo/64FrA0QkjIeNeGnoA2YyZ6bBUxpFUyqhJ8VbrDhXEFH+6LHMOYrpzX/ZQ==}
+ dependencies:
+ '@vue/reactivity': 3.4.8
+ '@vue/shared': 3.4.8
+ dev: false
+
/@vue/runtime-dom@3.3.11:
resolution: {integrity: sha512-OlhtV1PVpbgk+I2zl+Y5rQtDNcCDs12rsRg71XwaA2/Rbllw6mBLMi57VOn8G0AjOJ4Mdb4k56V37+g8ukShpQ==}
dependencies:
csstype: 3.1.3
dev: false
+ /@vue/runtime-dom@3.4.8:
+ resolution: {integrity: sha512-L4gZcYo8f3d7rQqQIHkPvyczkjjQ55cJqz2G0v6Ptmqa1mO2zkqN9F8lBT6aGPYy3hd0RDiINbs4jxhSvvy10Q==}
+ dependencies:
+ '@vue/runtime-core': 3.4.8
+ '@vue/shared': 3.4.8
+ csstype: 3.1.3
+ dev: false
+
/@vue/server-renderer@3.3.11(vue@3.3.11):
resolution: {integrity: sha512-AIWk0VwwxCAm4wqtJyxBylRTXSy1wCLOKbWxHaHiu14wjsNYtiRCSgVuqEPVuDpErOlRdNnuRgipQfXRLjLN5A==}
peerDependencies:
vue: 3.4.5(typescript@5.3.3)
dev: false
+ /@vue/server-renderer@3.4.8(vue@3.4.8):
+ resolution: {integrity: sha512-pBeHM59Owevr3P0Fl1XOjBmq4DTy5JDcjMG4NuzJEVDlZYzY8fHybx0wdjkY5lK5mCtUyBtw6Mz4d87aosc1Sw==}
+ peerDependencies:
+ vue: 3.4.8
+ dependencies:
+ '@vue/compiler-ssr': 3.4.8
+ '@vue/shared': 3.4.8
+ vue: 3.4.8(typescript@5.3.3)
+ dev: false
+
/@vue/shared@3.3.11:
resolution: {integrity: sha512-u2G8ZQ9IhMWTMXaWqZycnK4UthG1fA238CD+DP4Dm4WJi5hdUKKLg0RMRaRpDPNMdkTwIDkp7WtD0Rd9BH9fLw==}
resolution: {integrity: sha512-6XptuzlMvN4l4cDnDw36pdGEV+9njYkQ1ZE0Q6iZLwrKefKaOJyiFmcP3/KBDHbt72cJZGtllAc1GaHe6XGAyg==}
dev: false
+ /@vue/shared@3.4.8:
+ resolution: {integrity: sha512-ChLCWzXiJboQ009oVkemhEoUdrxHme7v3ip+Kh+/kDDeF1WtHWGt0knRLGm1Y4YqCRTSs9QxsZIY8paJj5Szrw==}
+ dev: false
+
/@vue/test-utils@2.4.3(@vue/server-renderer@3.3.11)(vue@3.3.11):
resolution: {integrity: sha512-F4K7mF+ad++VlTrxMJVRnenKSJmO6fkQt2wpRDiKDesQMkfpniGWsqEi/JevxGBo2qEkwwjvTUAoiGJLNx++CA==}
peerDependencies:
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
- dev: true
/minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
- supports-color
dev: false
+ /simple-git@3.22.0:
+ resolution: {integrity: sha512-6JujwSs0ac82jkGjMHiCnTifvf1crOiY/+tfs/Pqih6iow7VrpNKRRNdWm6RtaXpvvv/JGNYhlUtLhGFqHF+Yw==}
+ dependencies:
+ '@kwsites/file-exists': 1.1.1
+ '@kwsites/promise-deferred': 1.1.1
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
dev: true
fsevents: 2.3.3
dev: true
+ /vitepress-translation-helper@0.1.3(vitepress@1.0.0-rc.35)(vue@3.4.8):
+ resolution: {integrity: sha512-KandbALKgfKmRwYBX1Wt/A/38fhACmK+962S3hYgdvzSgwM2EOO5XgEUxPKXEil5kR1eNZKJJIPbQp52h8kCpA==}
+ hasBin: true
+ peerDependencies:
+ vitepress: 1.0.0-rc.36
+ vue: ^3.4.8
+ dependencies:
+ minimist: 1.2.8
+ simple-git: 3.22.0
+ vitepress: 1.0.0-rc.35(@algolia/client-search@4.19.1)(search-insights@2.7.0)(typescript@5.3.3)
+ vue: 3.4.8(typescript@5.3.3)
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/vitepress@1.0.0-rc.35(@algolia/client-search@4.19.1)(search-insights@2.7.0)(typescript@5.3.3):
resolution: {integrity: sha512-+2VnFwtYIiKWWAnMjWg7ik0PfsUdrNoZIZKeu5dbJtrkzKO/mTvlA3owiT5VBKJsZAgI17B5UV37aYfUvGrN6g==}
hasBin: true
typescript: 5.3.3
dev: false
+ /vue@3.4.8(typescript@5.3.3):
+ resolution: {integrity: sha512-vJffFOe6DqWsAI10v3tDhb1nJrj7CF3CbdQwOznywAsFNoyvrQ1AWQdcIWJpmRpRnw7NFzstzh6fh4w7n1PNdg==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@vue/compiler-dom': 3.4.8
+ '@vue/compiler-sfc': 3.4.8
+ '@vue/runtime-dom': 3.4.8
+ '@vue/server-renderer': 3.4.8(vue@3.4.8)
+ '@vue/shared': 3.4.8
+ typescript: 5.3.3
+ dev: false
+
/w3c-hr-time@1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
deprecated: Use your platform's native performance.now() and performance.timeOrigin.