Skip to content

Translations guide #825

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/.vuepress/components/guide/contributing/translations-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const labels = {
language: 'Language',
github: 'GitHub',
lastCommit: 'Last commit',
last90Days: 'Last 90 days',
loadDetails: 'Load Details',
commits: 'commits',
loading: 'Loading...'
}

// Repos are in alphabetical order by the language code
// You may need to clear your sessionStorage when adding a new item to this list
export const repos = [
{ lang: 'en-us', owner: 'vuejs', repo: 'docs-next', branch: 'master', url: 'https://v3.vuejs.org/' },
{ lang: 'id', owner: 'vuejs-id', repo: 'docs-next', branch: 'indonesian' },
{ lang: 'ja', owner: 'vuejs-jp', repo: 'ja.vuejs.org', branch: 'lang-ja', url: 'https://v3.ja.vuejs.org/' },
{ lang: 'ko', owner: 'vuejs-kr', repo: 'docs-next', branch: 'rootKoKr', url: 'https://v3.ko.vuejs.org/' },
{ lang: 'pt-br', owner: 'vuejs-br', repo: 'docs-next', branch: 'master', url: 'https://vuejsbr-docs-next.netlify.app/' },
{ lang: 'ru', owner: 'translation-gang', repo: 'docs-next', branch: 'master' },
{ lang: 'zh-cn', owner: 'vuejs', repo: 'docs-next-zh-cn', branch: 'master', url: 'https://v3.cn.vuejs.org/' }
]
206 changes: 206 additions & 0 deletions src/.vuepress/components/guide/contributing/translations.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<template>
<table>
<thead>
<tr>
<th>{{ labels.language }}</th>
<th>{{ labels.github }}</th>
<th>{{ labels.lastCommit }}</th>
<th>{{ labels.last90Days }}</th>
</tr>
</thead>
<tbody>
<tr v-for="({ lang, owner, repo, url, count, date }, index) in merged">
<td>
<a v-if="url" :href="url" target="_blank">
{{ lang }} <OutboundLink />
</a>
<template v-else>
{{ lang }}
</template>
</td>
<td>
<a :href="`https://github.com/${owner}/${repo}/`" target="_blank">{{ owner }}/{{ repo }} <OutboundLink /></a>
</td>
<template v-if="showLoadButton">
<td v-if="index === 0" colspan="2" :rowspan="merged.length" class="load-cell">
<button @click="load">{{ labels.loadDetails }}</button>
</td>
</template>
<template v-else>
<td>{{ date }}</td>
<td>
{{ count }}{{ count === 100 ? '+' : '' }}
<template v-if="typeof count === 'number'">
{{ labels.commits }}
</template>
</td>
</template>
</tr>
</tbody>
</table>
</template>

<script>
import { labels, repos } from './translations-data.js'

const getLastDate = async ({ owner, repo, branch }) => {
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/branches/${branch}`)

const data = await response.json()

const dateTime = data.commit.commit.committer.date

return dateTime.split('T')[0]
}

const DATE_90_DAYS_AGO = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toJSON().replace(/\.\d*/, '')

const commitCount = async ({ owner, repo }) => {
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits?since=${DATE_90_DAYS_AGO}&per_page=100`)

const data = await response.json()

return data.length
}

export default {
name: 'translations',

data () {
const dates = {}

for (const { lang } of repos) {
dates[lang] = null
}

return {
showLoadButton: true,
dates,
counts: { ...dates },
labels,
repos
}
},

computed: {
merged () {
return this.repos.map(repo => ({
...repo,
date: this.dates[repo.lang],
count: this.counts[repo.lang]
}))
}
},

mounted () {
let stats = null

try {
stats = JSON.parse(sessionStorage.getItem('translation-stats'))
} catch {
}

if (!stats) {
return
}

const { date, counts, dates } = stats

if (!date || date + 3 * 60 * 60 * 1000 < Date.now()) {
return
}

this.dates = dates
this.counts = counts
this.showLoadButton = false
},

methods: {
async load () {
this.showLoadButton = false

await Promise.all(this.repos.map(this.loadRepo))

this.saveStats()
},

async loadRepo (repo) {
await this.loadLastCommit(repo)

return this.loadCommitCount(repo)
},

async loadLastCommit (repo) {
const { lang } = repo

this.dates[lang] = labels.loading

let date = '-'

try {
date = await getLastDate(repo)
} catch {
}

this.dates[lang] = date
},

async loadCommitCount (repo) {
const { lang } = repo

const date = this.dates[lang]
let count = 0

if (date === '-') {
count = '-'
} else if (date > DATE_90_DAYS_AGO) {
this.counts[lang] = labels.loading

try {
count = await commitCount(repo)
} catch {
count = '-'
}
}

this.counts[lang] = count
},

saveStats () {
const data = {
date: Date.now(),
counts: this.counts,
dates: this.dates
}

// GitHub limits request rates, so we store the stats in sessionStorage
sessionStorage.setItem('translation-stats', JSON.stringify(data))
}
}
}
</script>

<style lang="scss" scoped>
@import "@theme/styles/_settings.scss";

.load-cell {
background: #f6f8fa;
text-align: center;

button {
padding: 4px 20px;
height: 50px;
border-radius: 9999px;
font-size: 1.05em;
font-weight: 600;
letter-spacing: 0.1em;
min-width: 8em;
color: #fff;
background-color: $green;
box-sizing: border-box;
border: 1px solid currentColor;
appearance: none;
cursor: pointer;
}
}
</style>
13 changes: 11 additions & 2 deletions src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,22 @@ module.exports = {
text: 'Translations',
link: '#',
items: [
// Translation maintainers: Please include the link below to the English documentation
// {
// text: 'English',
// link: 'https://v3.vuejs.org/'
// },
{
text: '中文',
link: 'https://v3.cn.vuejs.org/'
},
{
text: '한국어',
link: 'https://v3.ko.vuejs.org/'
},
{
text: '中文',
link: 'https://v3.cn.vuejs.org/'
text: 'More Translations',
link: '/guide/contributing/translations#community-translations'
}
]
}
Expand Down
4 changes: 1 addition & 3 deletions src/community/join.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,9 @@ Apart from answering questions and sharing resources in the forum and chat, ther

### Translate Docs

Vue has already spread across the globe, with even the core team in at least half a dozen timezones. [The forum](https://forum.vuejs.org/) includes 7 languages and counting and many of our docs have [actively-maintained translations](https://github.com/vuejs?utf8=%E2%9C%93&q=vuejs.org). We're very proud of Vue's international reach, but we can do even better.

I hope that right now, you're reading this sentence in your preferred language. If not, would you like to help us get there?

If so, please feel free to fork the repo for [these docs](https://github.com/vuejs/vuejs.org/) or for any other officially maintained documentation, then start translating. Once you've made some progress, open an issue or pull request in the main repo and we'll put out a call for more contributors to help you out.
See the [Translations guide](/guide/contributing/translations.html) for more details on how you can get involved.

### Become a Community Leader

Expand Down
40 changes: 36 additions & 4 deletions src/guide/contributing/translations.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
# Translations

Vue has spread across the globe, with the core team being in at least half a dozen different timezones. [The forum](https://forum.vuejs.org/) includes 7 languages and counting and many of our docs have [actively-maintained translations](https://github.com/vuejs?utf8=%E2%9C%93&q=vuejs.org). We're very proud of Vue's international reach, but we can do even better.
Vue has spread across the globe, with the core team being in at least half a dozen different timezones. The community is growing all the time and we want to make the documentation accessible to as many people as possible.

## Can we start translating Vue 3 docs?
Providing translations for the documentation is not something that the core team can manage alone. Thankfully, we have a great community of translators making contributions both large and small. If you've been thinking about contributing to the project, perhaps this is a good place to start?

Yes! We are ready for translation!
## Community translations

The table below lists GitHub repositories for community translations. These are translations made by the community, for the community. Some of these translations may be incomplete but they can still make the Vue experience significantly more enjoyable for readers who prefer these languages.

For completeness, we've also included the official documentation in the list.

<guide-contributing-translations />

Thank you to everyone who has contributed to these translations. Your hard work is very much appreciated.

## How can I get involved with translations?

The best way to get started is to check out [this pinned issue](https://github.com/vuejs/docs-next/issues/478) that contains active discussions on the various initiatives happening in the community.
The first step is to check whether there is an existing translation for the relevant language. In addition to the table above, a good place to start is [this pinned issue](https://github.com/vuejs/docs-next/issues/478), which is used to keep track of the various translation initiatives happening in the community.

If there's already an active translation then there are various ways you can help out. The GitHub repository should be a good place to start gathering information about how a particular translation is managed and who does what. All translation repositories should allow you to file issues and open Pull Requests if you have suggestions for improving the translation.

## What if there isn't an existing translation?

If you want to start a new translation then please do. You don't need our permission to start but you should read the rest of this page carefully to make sure you're clear about what's involved.

Before you start, you might want to check whether there was a community translation for Vue 2. [This pinned issue](https://github.com/vuejs/vuejs.org/issues/2015) from the Vue 2 documentation may help.

Working on a translation is more fun, and more likely to succeed, if there are multiple contributors. Even if you don't know anyone personally who can help out you may be able to find other translators from within the Vue community.

The documentation is constantly being updated. Many changes are small and don't directly impact the translations but others make important improvements that also need translating. Before you start work on a new translation you may want to take a look at the GitHub repositories for some other languages to get a sense of how they handle the update process.

When you first start a translation, you may want to use a personal GitHub repository. That's fine, so long as it's publicly accessible and open to contributions from others. Make sure the *Issues* tab is enabled in the repository's settings. You can migrate the repository to a shared organization at a later stage.

Once you start a translation, be sure to add it to [the pinned issue](https://github.com/vuejs/docs-next/issues/478) so that the rest of the community can find it.

We also encourage you to update the root-level `README.md` at an early stage. Most translations add extra information to help potential contributors get involved.

## Can I add my translation to this page?

If you've translated more than half of the documentation then please open a Pull Request to add your repository to the table of community translations on this page.

The official documentation is deployed on [Netlify](https://url.netlify.com/HJ8X2mxP8). We encourage you to do the same. Some community translators use their own Netlify accounts but we're happy to host community translations on our account once they're at an advanced stage.