diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index ea0d011d..4f9ce96e 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -1,4 +1,4 @@ -import type {Config} from '@docusaurus/types'; +import type { Config } from '@docusaurus/types'; import type * as Preset from '@docusaurus/preset-classic'; import { EnumChangefreq } from 'sitemap'; @@ -13,265 +13,241 @@ import { TWITTER_URL } from './constants'; import lightCodeTheme from './src/themes/prismLight'; import darkCodeTheme from './src/themes/prismDark'; -import { getTranslationProgress } from './src/api/crowdin.js'; -const translationProgress = getTranslationProgress(); +import { getTranslationProgress, LanguageProgress } from './src/api/crowdin'; -const config: Config = { - title: 'Task', - tagline: 'A task runner / simpler Make alternative written in Go ', - url: 'https://taskfile.dev', - baseUrl: '/', - onBrokenLinks: 'warn', - onBrokenMarkdownLinks: 'warn', - favicon: 'img/favicon.ico', +function localeConfig(name: string, locale: string, translationProgress: Map) { + let languageProgress = translationProgress.get(locale); + return { + label: `${name} (${languageProgress.approvalProgress || 0}%)`, + direction: languageProgress.language.textDirection, + htmlLang: languageProgress.language.locale, + } +} - organizationName: 'go-task', - projectName: 'task', - deploymentBranch: 'gh-pages', +export default async function createConfigAsync(): Promise { + var translationProgress = await getTranslationProgress(); + return { + title: 'Task', + tagline: 'A task runner / simpler Make alternative written in Go ', + url: 'https://taskfile.dev', + baseUrl: '/', + onBrokenLinks: 'warn', + onBrokenMarkdownLinks: 'warn', + favicon: 'img/favicon.ico', - i18n: { - defaultLocale: 'en', - locales: [ - 'en', - 'es-ES', - 'fr-FR', - 'ja-JP', - 'pt-BR', - 'ru-RU', - 'tr-TR', - 'zh-Hans' - ], - localeConfigs: { - en: { - label: 'English', - direction: 'ltr', - htmlLang: 'en-US' - }, - 'es-ES': { - label: `Español (${translationProgress['es-ES'] || 0}%)`, - direction: 'ltr', - htmlLang: 'es-ES' - }, - 'fr-FR': { - label: `Français (${translationProgress['fr'] || 0}%)`, - direction: 'ltr', - htmlLang: 'fr-FR' - }, - 'ja-JP': { - label: `日本語 (${translationProgress['ja'] || 0}%)`, - direction: 'ltr', - htmlLang: 'ja-JP' - }, - 'pt-BR': { - label: `Português (${translationProgress['pt-BR'] || 0}%)`, - direction: 'ltr', - htmlLang: 'pt-BR' - }, - 'ru-RU': { - label: `Pусский (${translationProgress['ru'] || 0}%)`, - direction: 'ltr', - htmlLang: 'ru-RU' - }, - 'tr-TR': { - label: `Türkçe (${translationProgress['tr'] || 0}%)`, - direction: 'ltr', - htmlLang: 'tr-TR' - }, - 'zh-Hans': { - label: `简体中文 (${translationProgress['zh-CN'] || 0}%)`, - direction: 'ltr', - htmlLang: 'zh-Hans' + organizationName: 'go-task', + projectName: 'task', + deploymentBranch: 'gh-pages', + + i18n: { + defaultLocale: 'en', + locales: [ + 'en', + 'es-ES', + 'fr', + 'ja', + 'pt-BR', + 'ru', + 'tr', + 'zh-Hans' + ], + localeConfigs: { + 'es-ES': localeConfig('Español', 'es-ES', translationProgress), + 'fr': localeConfig('Français', 'fr', translationProgress), + 'ja': localeConfig('日本語', 'ja', translationProgress), + 'pt-BR': localeConfig('Português', 'pt-BR', translationProgress), + 'ru': localeConfig('Pусский', 'ru', translationProgress), + 'tr': localeConfig('Türkçe', 'tr', translationProgress), + 'zh-Hans': localeConfig('简体中文', 'zh-CN', translationProgress), } - } - }, + }, - presets: [ - [ - 'classic', - { - docs: { - routeBasePath: '/', - sidebarPath: './sidebars.ts', - remarkPlugins: [remarkGithub, remarkGfm], - includeCurrentVersion: true, - versions: { - current: { - label: `Next 🚧`, - path: 'next', - badge: false - }, - latest: { - label: 'Latest', - badge: false + presets: [ + [ + 'classic', + { + docs: { + routeBasePath: '/', + sidebarPath: './sidebars.ts', + remarkPlugins: [remarkGithub, remarkGfm], + includeCurrentVersion: true, + versions: { + current: { + label: `Next 🚧`, + path: 'next', + badge: false + }, + latest: { + label: 'Latest', + badge: false + } } + }, + blog: {}, + theme: { + customCss: [ + './src/css/custom.css', + './src/css/carbon.css', + ] + }, + gtag: { + trackingID: 'G-4RT25NXQ7N', + anonymizeIP: true + }, + sitemap: { + changefreq: EnumChangefreq.WEEKLY, + priority: 0.5, + ignorePatterns: ['/tags/**'] } - }, - blog: {}, - theme: { - customCss: [ - './src/css/custom.css', - './src/css/carbon.css', - ] - }, - gtag: { - trackingID: 'G-4RT25NXQ7N', - anonymizeIP: true - }, - sitemap: { - changefreq: EnumChangefreq.WEEKLY, - priority: 0.5, - ignorePatterns: ['/tags/**'] - } - } satisfies Preset.Options, - ] - ], + } satisfies Preset.Options, + ] + ], - scripts: [ - { - src: '/js/carbon.js', - async: true - } - ], - - themeConfig:{ - metadata: [ + scripts: [ { - name: 'og:image', - content: 'https://taskfile.dev/img/og-image.png' + src: '/js/carbon.js', + async: true } ], - navbar: { - title: 'Task', - logo: { - alt: 'Task Logo', - src: 'img/logo.svg' - }, - items: [ - { - type: 'doc', - docId: 'intro', - position: 'left', - label: 'Docs' - }, - { - to: 'blog', - label: 'Blog', - position: 'left' - }, - { - to: '/donate', - position: 'left', - label: 'Donate' - }, - { - type: 'docsVersionDropdown', - position: 'right', - dropdownActiveClassDisabled: true, - }, - { - type: 'localeDropdown', - position: 'right', - dropdownItemsAfter: [ - { - to: '/translate/', - label: 'Help Us Translate' - } - ] - }, - { - href: GITHUB_URL, - position: 'right', - className: "header-icon-link icon-github", - }, - { - href: DISCORD_URL, - position: 'right', - className: "header-icon-link icon-discord", - }, - { - href: TWITTER_URL, - position: 'right', - className: "header-icon-link icon-twitter", - }, - { - href: MASTODON_URL, - rel: 'me', - position: 'right', - className: "header-icon-link icon-mastodon", - } - ] - }, - footer: { - style: 'dark', - links: [ - { - title: 'Pages', - items: [ - { - label: 'Installation', - to: '/installation/' - }, - { - label: 'Usage', - to: '/usage/' - }, - { - label: 'Donate', - to: '/donate/' - } - ] - }, - { - title: 'Community', - items: [ - { - label: 'GitHub', - href: GITHUB_URL - }, - { - label: 'Twitter', - href: TWITTER_URL - }, - { - label: 'Mastodon', - href: MASTODON_URL, - rel: 'me' - }, - { - label: 'Discord', - href: DISCORD_URL - }, - { - label: 'OpenCollective', - href: 'https://opencollective.com/task' - } - ] - }, - { - items: [ - { - html: 'Deploys by Netlify' - } - ] - } - ] - }, - prism: { - theme: lightCodeTheme, - darkTheme: darkCodeTheme, - additionalLanguages: [ - "bash", // aka. shell - "json", - "powershell" - ] - }, - // NOTE(@andreynering): Don't worry, these keys are meant to be public =) - algolia: { - appId: '7IZIJ13AI7', - apiKey: '34b64ae4fc8d9da43d9a13d9710aaddc', - indexName: 'taskfile' - } - } satisfies Preset.ThemeConfig, -}; -export default config; + themeConfig:{ + metadata: [ + { + name: 'og:image', + content: 'https://taskfile.dev/img/og-image.png' + } + ], + navbar: { + title: 'Task', + logo: { + alt: 'Task Logo', + src: 'img/logo.svg' + }, + items: [ + { + type: 'doc', + docId: 'intro', + position: 'left', + label: 'Docs' + }, + { + to: 'blog', + label: 'Blog', + position: 'left' + }, + { + to: '/donate', + position: 'left', + label: 'Donate' + }, + { + type: 'docsVersionDropdown', + position: 'right', + dropdownActiveClassDisabled: true, + }, + { + type: 'localeDropdown', + position: 'right', + dropdownItemsAfter: [ + { + to: '/translate/', + label: 'Help Us Translate' + } + ] + }, + { + href: GITHUB_URL, + position: 'right', + className: "header-icon-link icon-github", + }, + { + href: DISCORD_URL, + position: 'right', + className: "header-icon-link icon-discord", + }, + { + href: TWITTER_URL, + position: 'right', + className: "header-icon-link icon-twitter", + }, + { + href: MASTODON_URL, + rel: 'me', + position: 'right', + className: "header-icon-link icon-mastodon", + } + ] + }, + footer: { + style: 'dark', + links: [ + { + title: 'Pages', + items: [ + { + label: 'Installation', + to: '/installation/' + }, + { + label: 'Usage', + to: '/usage/' + }, + { + label: 'Donate', + to: '/donate/' + } + ] + }, + { + title: 'Community', + items: [ + { + label: 'GitHub', + href: GITHUB_URL + }, + { + label: 'Twitter', + href: TWITTER_URL + }, + { + label: 'Mastodon', + href: MASTODON_URL, + rel: 'me' + }, + { + label: 'Discord', + href: DISCORD_URL + }, + { + label: 'OpenCollective', + href: 'https://opencollective.com/task' + } + ] + }, + { + items: [ + { + html: 'Deploys by Netlify' + } + ] + } + ] + }, + prism: { + theme: lightCodeTheme, + darkTheme: darkCodeTheme, + additionalLanguages: [ + "bash", // aka. shell + "json", + "powershell" + ] + }, + // NOTE(@andreynering): Don't worry, these keys are meant to be public =) + algolia: { + appId: '7IZIJ13AI7', + apiKey: '34b64ae4fc8d9da43d9a13d9710aaddc', + indexName: 'taskfile' + } + } satisfies Preset.ThemeConfig, + }; +}; diff --git a/website/src/api/crowdin.js b/website/src/api/crowdin.js deleted file mode 100644 index 71653bf8..00000000 --- a/website/src/api/crowdin.js +++ /dev/null @@ -1,46 +0,0 @@ -const crowdin = require('@crowdin/crowdin-api-client'); -const personalToken = process.env.CROWDIN_PERSONAL_TOKEN; -const projectId = '574591'; - -/** - * Initialization of crowdin client - * @return {object} crowdin client - */ -const initClient = () => { - if (!personalToken) { - console.warn( - 'No crowdin personal token, some features might not work as expected' - ); - return null; - } - - return new crowdin.default({ - token: personalToken - }); -}; - -/** - * Get translation progress - * @return {object} translation progress - */ -export async function getTranslationProgress() { - let translationProgress = {}; - const { translationStatusApi } = initClient() || {}; - - if (!translationStatusApi) { - return translationProgress; - } - - await translationStatusApi - .getProjectProgress(projectId) - .then((res) => { - res.data.forEach((item) => { - translationProgress[item.data.languageId] = item.data.approvalProgress; - }); - }) - .catch((err) => { - console.error(err); - }); - - return translationProgress; -} diff --git a/website/src/api/crowdin.ts b/website/src/api/crowdin.ts new file mode 100644 index 00000000..6de5e482 --- /dev/null +++ b/website/src/api/crowdin.ts @@ -0,0 +1,36 @@ +import crowdin, { Credentials, TranslationStatusModel, ResponseObject, LanguagesModel, Languages } from '@crowdin/crowdin-api-client'; + +const projectId = 574591; +const credentials: Credentials = { + token: process.env.CROWDIN_PERSONAL_TOKEN, +}; + +// This adds the language field to LanguageProgress which is missing in the original model +export interface LanguageProgress extends TranslationStatusModel.LanguageProgress { + language: LanguagesModel.Language; +} + +const initClient = () => { + if (credentials.token === '') { + console.warn( + 'No crowdin personal token, some features might not work as expected' + ); + return null; + } + return new crowdin(credentials); +}; + +export async function getTranslationProgress(): Promise> { + var progress = new Map(); + await initClient().translationStatusApi + .getProjectProgress(projectId) + .then((res) => { + res.data.forEach((item: ResponseObject) => { + progress.set(item.data.language.id, item.data); + }); + }) + .catch((err) => { + console.error(err); + }); + return progress; +}