Skip to content

Commit 0187f7e

Browse files
Jinjiangposva
andauthored
docs: non-checkpoint-branch workflow (#1855)
* add translation status on page top * refactor: use mjs and promises * chore: format contribution guidelines * chore: update translation workflow to remove checkpoint branches * fix: wrong git diff arg in compare-to-translate * chore: make the translation status generator compatible with legacy log format * chore: update translation workflow guide and ignore translation-status.json * chore: add docs:preview command * chore: improve translation workflow in docs * chore: update contributing docs * chore: update contributing docs * Apply suggestions from code review Co-authored-by: Eduardo San Martin Morote <[email protected]> * Update contributing.md --------- Co-authored-by: Eduardo San Martin Morote <[email protected]> Co-authored-by: Eduardo San Martin Morote <[email protected]>
1 parent 0b90a50 commit 0187f7e

File tree

9 files changed

+881
-585
lines changed

9 files changed

+881
-585
lines changed

.github/contributing.md

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -117,40 +117,51 @@ Currently, all the docs can be found in `packages/docs`. It contains the English
117117

118118
Besides that, the `.vitepress` sub-folder is used to put the config and theme, including the i18n information.
119119

120-
Consider the following two options in order to contribute to the translations:
120+
Contributing to the English docs is the same as contributing to the source code. You can simply create a pull request to our GitHub repo. However, if you would like to contribute to the translations, there are 2 options and some extra steps to follow:
121121

122122
### Translate in a `<lang>` sub-folder and host it on our official repo
123123

124-
If you want to start translating the docs in a new language:
124+
If you want to start translating the docs in a _new_ language:
125125

126126
1. Create the corresponding `<lang>` sub-folder for your translation.
127127
2. Modify the i18n config in `.vitepress` sub-folder.
128128
3. Translate the docs and run the doc site to self-test locally.
129-
4. Once you have done all above, create a pull request to our GitHub repo.
129+
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 would be stored in the status file `packages/docs/.vitepress/translation-status.json`. _It's important for the long-term maintenance since all the further translation sync-ups would be based on their previous checkpoints._ Usually you can skip the commit argument because the default value is `main`.
130+
5. Commit all the changes and create a pull request to our GitHub repo.
130131

131-
If you want to maintain a existing translation:
132+
We will have a paragraph right at the top of each translation page that shows the status of the translation. That way, users can easily figure out if the translation is up-to-date or lags behind the English version.
132133

133-
1. (Repo permission required) First of all, make sure there is a _checkpoint_ branch for the language. Usually it's named as `docs-sync-<lang>`. Notice that:
134-
- This branch is always synced to the commit of the original docs that the latest translation of your language is corresponding to. Like `docs-sync-zh` is always to the commit of the original docs that the latest Chinese translation is corresponding to.
135-
- Technically, this checkpoint branch should be only updated if the translation is synced to a nearer commit of the original docs. Usually the commit is the HEAD of the `main` branch at that moment.
136-
2. See what translation you need to do to sync up with the original docs. There are 2 popular ways:
137-
- Git diff command: e.g. `git diff docs-sync-zh..main packages/docs # > debug.log`, or
138-
- GitHub Compare page: e.g. https://github.com/vuejs/router/compare/docs-sync-zh...main (only see the changes in `packages/docs/*`)
139-
3. Create your own branch and start the translation update, following the diff or compare.
140-
4. Once you have done all above, create a pull request to our GitHub repo.
141-
- It's highly recommended to commit with message like `docs(<lang>): sync update to <the-latest-commit>`. e.g. `docs(zh): sync update to e008551`.
142-
5. (Repo permission required) **VERY IMPORTANT**: after the pull request is merged, for the future batch of sync-up, do another merge from the latest commit at that moment to the checkpoint branch. e.g. merge commit `e008551` to branch `docs-sync-zh`.
134+
Speaking of the up-to-date translation, we also need good long-term maintenance for every language. If you want to _update_ an existing translation:
143135

144-
For more real examples, please check out [all the PRs with title "docs(zh): sync" after 2023-01-01](https://github.com/vuejs/router/pulls?q=is%3Apr+created%3A%3E2023-01-01+docs%28zh%29+sync).
136+
1. See what translation you need to sync up with the original docs. There are 2 popular ways:
137+
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`. And 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
138+
2. Via a local command: `pnpm run docs:compare-to-translate <lang> [<commit>]`.
139+
2. Create your own branch and start the translation update, following the previous comparison.
140+
3. Create a checkpoint for your language by running `pnpm run docs:translation-status <lang> [<commit>]`.
141+
4. Commit all the changes and create a pull request to our GitHub repo.
142+
143+
<!-- TODO: add an example once we have got one -->
145144

146145
### Self-host the translation
147146

148147
You can also host the translation on your own. To create one, just simply fork our GitHub repo and change the content and site config in `packages/docs`. To long-term maintain it, we _highly recommend_ a similar way that we do above for our officially hosted translations:
149148

150-
1. Ensure you create a _checkpoint branch_ (for example, a branch named sync). This branch should always align with the commit of the original documentation that corresponds to your most recent translation.
151-
2. Utilize the diff result between the latest official repository and your own by using the git diff command or the GitHub Compare page to guide your translation.
152-
3. Complete the translation process.
153-
4. Update the _checkpoint branch_ accordingly.
149+
- Ensure you maintain the _checkpoint_ properly. And also ensure the _translation status_ is well-displayed on the top of each translation page.
150+
- Utilize the diff result between the latest official repository and your own checkpoint to guide your translation.
151+
152+
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:
153+
154+
```bash
155+
# prepare the upstream remote
156+
git remote add upstream [email protected]:vuejs/router.git
157+
git fetch upstream main
158+
159+
# set the checkpoint
160+
pnpm run docs:translation-status <lang> upstream/main
161+
162+
# get the diff result
163+
pnpm run docs:compare-to-translate <lang> upstream/main
164+
```
154165

155166
<!-- TODO: add an example once we have got one -->
156167

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
"size": "node scripts/check-size.mjs",
1414
"build": "pnpm run -r build",
1515
"build:dts": "pnpm run -r build:dts",
16+
"docs": "pnpm run --filter ./packages/docs -r docs",
1617
"docs:api": "pnpm run --filter ./packages/docs -r docs:api",
18+
"docs:compare-to-translate": "pnpm run --filter ./packages/docs -r docs:compare-to-translate",
19+
"docs:translation-status": "pnpm run --filter ./packages/docs -r docs:translation-status",
1720
"docs:build": "pnpm run docs:api && pnpm run --filter ./packages/docs -r docs:build",
21+
"docs:preview": "pnpm run --filter ./packages/docs -r docs:preview",
1822
"play": "pnpm run -r play",
1923
"build:size": "pnpm run -r build:size",
2024
"lint": "pnpm run lint:script && pnpm run lint:html",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<script lang="ts">
2+
const originalLang = 'root'
3+
const i18nLabels: {
4+
[lang: string]: string
5+
} = {
6+
en: 'The translation is synced to the docs on ${date} of which the commit hash is <code>${hash}</code>.',
7+
zh: '该翻译已同步到了 ${date} 的版本,其对应的 commit hash 是 <code>${hash}</code>。',
8+
}
9+
</script>
10+
11+
<script setup lang="ts">
12+
import { computed } from 'vue'
13+
import { useData } from 'vitepress'
14+
import status from '../../translation-status.json'
15+
16+
const { site } = useData()
17+
const label = computed<string>(() => {
18+
const localeIndex = site.value.localeIndex
19+
if (!localeIndex || localeIndex === originalLang || !status[localeIndex]) {
20+
return ''
21+
}
22+
const { date, hash } = status[localeIndex]
23+
return (i18nLabels[localeIndex] || i18nLabels.en)
24+
.replace('${date}', `<time>${date}</time>`)
25+
.replace('${hash}', `<code>${hash.substring(0, 7)}</code>`)
26+
})
27+
</script>
28+
29+
<template>
30+
<div v-if="label" class="text-status" v-html="label"></div>
31+
</template>
32+
33+
<style scoped>
34+
.text-status {
35+
padding: 1em 1.25em;
36+
font-size: small;
37+
text-align: right;
38+
color: var(--vp-c-text-2);
39+
}
40+
</style>

packages/docs/.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Theme, useData } from 'vitepress'
33
import DefaultTheme from 'vitepress/theme'
44
import AsideSponsors from './components/AsideSponsors.vue'
55
// import HomeSponsors from './components/HomeSponsors.vue'
6+
import TranslationStatus from './components/TranslationStatus.vue'
67
import './styles/vars.css'
78
import './styles/sponsors.css'
89
import VueSchoolLink from './components/VueSchoolLink.vue'
@@ -14,6 +15,7 @@ const theme: Theme = {
1415
return h(DefaultTheme.Layout, null, {
1516
// 'home-features-after': () => h(HomeSponsors),
1617
'aside-ads-before': () => h(AsideSponsors),
18+
'doc-before': () => h(TranslationStatus),
1719
})
1820
},
1921

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"zh": {
3+
"hash": "1a3a28f",
4+
"date": "2023-04-08"
5+
}
6+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// @ts-check
2+
import { readFile } from 'fs/promises'
3+
import simpleGit from 'simple-git'
4+
5+
// The path to the translation status file.
6+
const STATUS_FILE_PATH = './.vitepress/translation-status.json'
7+
8+
const usage = `
9+
Usage: pnpm run docs:compare-to-translate <locale> [<commit>]
10+
locale: The target locale to compare.
11+
commit: The target commit to compare. It could be a branch, a tag, or a hash. Default to 'main'.`
12+
13+
async function getLocaleHash (lang) {
14+
try {
15+
const content = await readFile(STATUS_FILE_PATH, 'utf8')
16+
const data = JSON.parse(content)
17+
return data[lang]?.hash
18+
} catch (err) {
19+
console.log('No previous status file. Will create a new one.')
20+
}
21+
}
22+
23+
async function main() {
24+
if (process.argv.find(arg => arg === '--help' || arg === '-h')) {
25+
console.log(usage)
26+
return
27+
}
28+
29+
const locale = process.argv[2]
30+
const commit = process.argv[3] || 'main'
31+
32+
const hash = await getLocaleHash(locale)
33+
if (hash) {
34+
console.log(`The last checkpoint of docs(${locale}) is "${hash}".\n`)
35+
const git = simpleGit()
36+
const result = await git.diff([`${hash}..${commit}`, '.'])
37+
console.log(result)
38+
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.`)
39+
} else {
40+
console.log(`No docs(${locale}) checkpoint found.\n`)
41+
console.log(usage)
42+
}
43+
}
44+
45+
main()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// @ts-check
2+
import { writeFile, readFile } from 'fs/promises'
3+
import simpleGit from 'simple-git'
4+
5+
// The path to the translation status file.
6+
const STATUS_FILE_PATH = './.vitepress/translation-status.json'
7+
8+
const usage = `
9+
Usage: pnpm run docs:translation-status <locale> [<commit>]
10+
locale: The target locale to update.
11+
commit: The target commit to update. It could be a branch, a tag, or a hash. Default to 'main'.`
12+
13+
async function getCommitInfo (commit) {
14+
try {
15+
const git = simpleGit()
16+
const log = await git.log([commit, '-n', '1'])
17+
const { hash, date } = log.latest
18+
return { hash, date: new Date(date).toISOString().substring(0, 10) }
19+
} catch (err) {
20+
return { hash: '', date: '' }
21+
}
22+
}
23+
24+
async function writeLangMap (lang, hash, date) {
25+
const data = {}
26+
try {
27+
const previousContent = await readFile(STATUS_FILE_PATH, 'utf8')
28+
const previousJson = JSON.parse(previousContent)
29+
Object.assign(data, previousJson)
30+
}
31+
catch (err) {
32+
console.log('No previous status file. Will create a new one.')
33+
}
34+
data[lang] = {
35+
hash,
36+
date,
37+
}
38+
await writeFile(STATUS_FILE_PATH, JSON.stringify(data, null, 2))
39+
}
40+
41+
async function main() {
42+
if (process.argv.find(arg => arg === '--help' || arg === '-h')) {
43+
console.log(usage)
44+
return
45+
}
46+
47+
const locale = process.argv[2]
48+
const commit = process.argv[3] || 'main'
49+
50+
const { hash, date } = await getCommitInfo(commit)
51+
if (!hash) {
52+
console.log(`❌ No commit found for "${commit}".`)
53+
return
54+
} else {
55+
await writeLangMap(locale, hash, date)
56+
console.log(`✅ Updated ${locale} to "${hash}" (${date})`)
57+
}
58+
}
59+
60+
main()

packages/docs/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
"scripts": {
77
"docs": "vitepress dev .",
88
"docs:api": "node run-typedoc.mjs",
9-
"docs:build": "vitepress build ."
9+
"docs:compare-to-translate": "node compare-to-translate.mjs",
10+
"docs:translation-status": "node generate-translation-status.mjs",
11+
"docs:build": "vitepress build .",
12+
"docs:preview": "vitepress preview ."
1013
},
1114
"dependencies": {
15+
"simple-git": "^3.18.0",
1216
"vitepress": "1.0.0-rc.31",
1317
"vue-router": "workspace:*"
1418
}

0 commit comments

Comments
 (0)