Skip to content

Commit

Permalink
Add Support for translated content (#7200)
Browse files Browse the repository at this point in the history
* Add i18n gem and point jekyll-generator-single-source to a topic branch

* Update Jekyll's config files and update the build commands

* Add locale
* Add path to translated_content
* Move extensions and hub_filters to app/_data we need to translate
  those (we'll need to make sure that `slug` doesn't get translated)

* Set I18n config and load locales from the _translated_content folder

* Add monkeypatches to jekyll and jekyll-include-cache

Modify them so that they look for in the _translated_content folder
first, and fall back to english.
For now, this only works for /includes/md, we might need to change it so
that it supports all includes.

* Add hook so that site.data looks for the files in
_translated_data/app/_data first and fallbacks to app/_data

* Add i18n keys to landing footer and nav-v2

* Load extension and categories from site.data and not from the site's config

* Only show edit link if the site is not in english

* Use site.data.extensions instead of site.config.extensions

* Add {% t key %} helper

* Add missing translation banner

* Add missin translation data to oas and plugin pages so that a banner is
rendered

* Translate static pages

Iterate over the static pages and check if there is a translated version
of them.
If there is, use the translated version, if not, fallback to english

* Set canonical url

English site: no changes
Japanese site:
  * If a page in docs.konghq.com doesn’t have a canonical link:
    - Japanese fallback to English: Add a canonical link to the docs.konghq.com site.
    - Otherwise, no need for a canonical link.
  * If a page in docs.konghq.com has a canonical link:
    - Japanese fallback to English: Add a canonical link to the docs.konghq.com site.
    - Otherwise, add a canonical link to the Japanese subdomain.

* Fix specs

* Change the placement of the banner

* Add translations to book.html

* Add translations to nav-links

* Add translations to docs-sidebar

* Modify the translation helper so that it returns valid liquid

* Add string translations to _includes/gateway-support

* Modify {% t %} so that it returns a parsed liquid template

* Add string translations to _includes/lts-changes

* Add string translations to app/_includes/gateway-support-third-party

* Make rubocop happy

* Move translated_content_path to an ENV variable

* Add hreflang tags

* Remove extra space

* Move translation keys to one file

* WIP: Add Tool that integrates with Smartling's API and sends files for
translation

Add basic configuration file, we'll need to tweak this accordingly.
TODO: read the files + pre-process them when calling .setFile

* [DOCU-3776] Set gtm value in jekyll.yml

* [DOCU-3776] Remove intercom, we no longer use it

* Fix exe/build and use strings to compare locale values

* [DOCU-3776] Don't generate BingSiteAuth.xml and google-site-verifications

* [DOCU-3776] Move vwo account_id to jekyll.yml and only run it in
production

* Don't translate hub_filters and categories for now.
We'll translate them when we translate the plugin hub

* Update code with a comment

Pages in app/<product> are not single source, so if they are translated
the corresponding docs_nav file must be translated too. We assume here that
they are translated at the same time.

* Looks like setFile is deprecated, use setFileFromLocalFilePath instead.

* Change the way TRANSLATED_CONTENT_PATH works so that it points to a
folder with several locales.

* Only use japanese version of an include if the page is translated

* Update latest version generator and productable so that they rely on the
edition and not relative_paths

* Make rubocop happy

* Update the way we handle overwriting the content of a page that isn't
single-sourced depending on whether the actual file is translated and
the nav file

* Remove hreflang for now

* [Plugin Hub] Add support for fetching content in other languages

* [Plugin Hub] Load the files in the corresponding locale depending on
whether the gateway version was translated or not, i.e. doc_nav is in
the locale

* Allow upload to receive a jobId in case something went during file
uploads

* Fix string interpolation

* Update upload tool so that it sends plugin files.

Limited to schemas, overview/_index.md and _metadata.

* Add missing string translation after rebase

* Make {% t %} tag support both string and variables as params

* Add string translations to plugin hub

* Remove links from translations, pass them as parameters

* Add double qoutes to translations

* Add translations for Plugins basic-examples tabs

* Disable search and skip search.html generation

Based on a new boolean config in jekyll.yml called `disable_search`.

* Make rubocop happy

* Bump jekyll-generator-single-source

* [Smartling] Send plugin files separately

* Rename $CONFIG_FILES to $JEKYLL_CONFIG_FILES, it appears tha
CONFIG_FILES is a reserved env variable in netlify even though it's not
listed as one

* Only translate top 10 plugins for now.

* Add list of plugins to translation config

* [Plugin Hub] Send includes to Smartling

* Remove app/CNAME file

It was used to set up the CNAME when the site was deployed via github
pages

* [Plugin Hub] Translate sidebar using string translations

We'll show the sidebar in japanese if the docs_nav for the corresponding
gateway release is available in japanese. Otherwise, we'll show the
english version.

This approach is slightly different to the one we take with the docs,
where we display the sidebar in japanese if both the docs_nav file and
the source file are available in japanese.
I'll try to take the same approach for consistency, but sidebars are
built differently, so it's tricky.

* Troubleshooting Require jekyll-kuma-plugins in a file instead of as a gem

* Update submodules before building the site

* Make rubocop happy

* [Smartling] Add yaml pre-processor

We need to annotate which keys we want to translated in YAML files.

* [Smartling] Prevent more data files from being translated.

* [Smartling] Pre-process plugins metadata files.

* [Smartling] Add translate/notranslate annotations to docs_nav files

* [Smartling] Add translate/notranslate annotations to data/extensions.yml

* Use jekyll_plugins to group gems in the Gemfile
This way they get required by Jekyll on build

Fixes the build in Ubuntu by loading the plugins correctly before
running the code. The problem was with the order the plugins were being loaded.
Which used to work because jekyll-generator-single source was being
manually required, but that was removed as part of
#7395.

Even without that required, it used to work because of the`priorities`.
The jekyll-generator-single-source had the highets and that's why it was
being loaded first. but now priorities changed so that no longer
applies.

Using the jekyll_plugins group in the Gemfile ensures that they are
loaded.

* [Smartling] Update download script

* Add an action that dispatches an event when the `main` branch is updated

* [Smartling] Use ja-JP as locale.
It should match the one set on Smartling's dashboard

* [Smartling] Us strings instead of boolean values for
`yaml_locale_detection` and `yaml_locale_substitution`

* [Smartling] Fix download script

* [Smartling] Only translate field descriptions and deprecation messages
when sending plugin schemas.

* Add missing dependencies to tools/smartling-integration

* [Smartling] Update config.yml to use the right locale, i.e. ja-JP

* [Smartling] Remove plugins config when uploading docs.

* [Smartling] Add github action that runs
tools/smartling-integration/updload_docs.js

* [Smartling] Fix an issue with the upload_plugins tool

There was an edge case when uploading plugin schemas.
When only one version was provided, the schemas weren't being
considered.

* [Smartling] Add github action that sends plugins for translation

* [Smartling] Extract markdown placeholders into a constant

* [Smartling] Add {: .*} (notes, warnings, etc) as placeholders so we
don't translate the text inside {: }

* [Smartling] Don't set `yfm_block_enabled`

It isn't necessary and was causing parsing problems. Frontmatter
translations are handled by setting the `yaml_front_matter` directive.

Also set `yaml_front_matter` to plugin pages

* [Smartling] Prevent code blocks from being translated in markdown files
using the `markdown_code_notranslate` directive

* [Smartling] Refacto Batch params creation and set the directive
smartling.markdown_html_strategy = ‘restore’ to MD files

This directive is not documented and restores the original html markup
that a markdown file has. It was provided by the Smartling Technical
Architect.

* [Smartling] Add post-processing to Markdown files on download

* [Smartling] Add script to test the integration.

* [DOCU-3774] Add copy for missing and no translations banner

* [DOCU-3779] Add hreflang tags

* [DOCU-3873] Handle canonical urls.

According to the following rules:
* All /latest/ or evergreen URLs (i.e plugin hub) should have self referencing canonicals 
* All /{version #}/ URLs should have a canonical that points to the /latest/
* Canonical urls in the JP site should point to  docs.jp.konghq.com
* Canonical urls in  docs.konghq.com, point to  http://docs.konghq.com

Context: Why not set the canonical to the default docs LP if the page is not translated?
The "JP" in the subdomain is a country code + the hreflang shows that everything under this subdomain structure is meant for Japan search results.
If we pointed the canonical to the default docs LP then we are essentially telling search engines that we do not want this content to show up in Japan.
Submitting a bulk number of URLs to search engines and then telling it not to index a chunk of those is confusing and can hurt us from a holistic level.
So even though it is in english, it is best to still leverage the jp subdomain structure to avoid indexing tension.

* [Smartling] Prevent mermaid diagrams from being translated

* [Smartling] Handle Rate Limits gracefully

* [Smartling] Increase timeout when downloading the files to account for
rate limiting and large amounts of files

Tested this locally with gateway 3.6.x ~ 340 files.

* Add sitemap index to the site and update Robots.txt accordingly

* [Smartling] Pre-process more data files

* [Smartling]: Translate changelogs

* [Smartling] Pre and Post process supported versions data files

* Fix smoke test

* Run smoke tests with JEKYLL_ENV=production so that the right config gets
picked up and the sitemap gets generated

The previous step builds the docs using JEKYLL_ENV=production, but
running netlify-dev, re-run the site using JEKYLL_ENV=development which
deletes the sitemap pages, because we use a generator to build those.

This didn't happen before because the sitemap was generated differently.
There was a file app/sitemap.xml, so running netlify dev would serve
this page from the cache.

* Fix smoke tests

Rely on redirects for the sitemap.
Tell Jekyll to use jekyll.yml when running netlify dev (only for smoke
tests) so that the sitemap gets generated using the right domain.

* [Smartling] Modify download so that it changes the name of
config/locales/en.yml to the provided LOCALE

* Use locale + country code for the site's locale

* Set default_locale on the site's config and use it in templates

* Fix monkey-patches so that yaml files treated like liquid work
with english and localized versions

* Update netlify so that it runs `git submodule update --init --recursive` before
building the site

* Include config in the job's name in Smartling

* Remove segment/analytics-next and use the inline script

* Add gtm tag if env == production and gtm_id is set

* [Smartling] Post-process markdown lists

Unfortunately, the {% if_version/endif_version %} tags get moved around
when we download the translations, so some post-processing is needed to
put them back into place.

* Check if site vairables are empty before rendering the analytics scripts

* Update spec after rebase

* Don't translate reference docs or admin-api-*.md files

* Update translation config file to match what has been translated

* Prevent some translations from being downloaded

* Always read the plugin's description from metadata

* Read a plugin's nav_title from the markdown file and fallback to english

* Set the correct @relative_path on plugin pages so that Jekyll can read
the correct file on render

If the locale is en use the relative path.
Otherwise:
* if a translation is available use it
* fallback to en

* Add sitemap redirect only to the english site

* Fix link to sitemap in robots.txt, the domain should always be
docs.konghq.com

* Run the sitemap generator in jp too but don't generate the sitemap
pages.
It sets seo-noindex and canonical_urls
  • Loading branch information
fabianrbz authored Nov 4, 2024
1 parent 67c3805 commit 0fd492b
Show file tree
Hide file tree
Showing 137 changed files with 7,781 additions and 890 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/dispatch-docs-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Dispatch docs update
on:
push:
branches:
- 'main'

jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.PAT }}
repository: Kong/docs.konghq.com-jp
event-type: DOCS_UPDATED
3 changes: 3 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ jobs:
exe/build
- name: Run Smoke Tests
env:
JEKYLL_ENV: production
JEKYLL_CONFIG_FILES: jekyll.yml
run: |
npm install -g wait-on
netlify dev & wait-on http://localhost:8888
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/send-docs-for-translation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Upload Docs for translation
on:
workflow_dispatch:
inputs:
product:
type: string
description: |
Kong product to translate.
If specified, only files related to that speciific product will be translated.
Otherwise, the config file in tools/smartling-integration/config.yml will be used.
versions:
type: string
description: |
This param only makes sense if the `product` is provided.
Comma-separated list of versions for a specific product to translate.
If not provided, the config file in tools/smartling-integration/config.yml will be used.
locale:
type: string
default: 'ja-JP'
description: "Target locale, it must match the same format that the Job has, e.g. `ja-JP`."
jobId:
type: string
description: "Smarting's JobUId in case we want to re-upload some files to an existing Job"

jobs:
upload-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: |
cd tools/smartling-integration
npm ci
- name: Run upload tool
run: |
node tools/smartling-integration/upload_docs.js
env:
PROJECT_ID: ${{ secrets.SMARTLING_PROJECT_ID }}
USER_IDENTIFIER: ${{ secrets.SMARTLING_USER_IDENTIFIER }}
USER_SECRET: ${{ secrets.SMARTLING_USER_SECRET }}
JOB_ID: ${{ github.event.inputs.jobId }}
LOCALE: ${{ github.event.inputs.locale }}
PRODUCT: ${{ github.event.inputs.product }}
VERSIONS: ${{ github.event.inputs.versions }}
41 changes: 41 additions & 0 deletions .github/workflows/send-plugins-for-translation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Upload Plugins for translation
on:
workflow_dispatch:
inputs:
versions:
type: string
description: |
Comma-separated list of gateway versions to translate.
If not provided, the config file in tools/smartling-integration/config.yml will be used.
locale:
type: string
default: 'ja-JP'
description: "Target locale, it must match the same format that the Job has, e.g. `ja-JP`."
jobId:
type: string
description: "Smarting's JobUId in case we want to re-upload some files to an existing Job"

jobs:
upload-plugins:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: |
cd tools/smartling-integration
npm ci
- name: Run upload tool
run: |
node tools/smartling-integration/upload_plugins.js
env:
PROJECT_ID: ${{ secrets.SMARTLING_PROJECT_ID }}
USER_IDENTIFIER: ${{ secrets.SMARTLING_USER_IDENTIFIER }}
USER_SECRET: ${{ secrets.SMARTLING_USER_SECRET }}
JOB_ID: ${{ github.event.inputs.jobId }}
LOCALE: ${{ github.event.inputs.locale }}
VERSIONS: ${{ github.event.inputs.versions }}
10 changes: 6 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

source 'https://rubygems.org'
gem 'jekyll'
gem 'jekyll-include-cache'
gem 'jekyll-redirect-from'
gem 'jekyll-generator-single-source'
gem 'kramdown-parser-gfm'
gem 'liquid-c'
gem 'rouge', '4.4.0'
gem 'activesupport'
gem 'nokogiri'
gem 'jekyll-kuma-plugins', path: './app/_src/.repos/kuma/jekyll-kuma-plugins'
gem 'jekyll-vite'
gem 'i18n'

group :jekyll_plugins do
gem 'jekyll-include-cache'
gem 'jekyll-redirect-from'
gem 'jekyll-generator-single-source', github: 'kong/jekyll-generator-single-source', branch: 'i18n-spike'
end

group :development do
gem 'pry'
Expand Down
15 changes: 8 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
PATH
remote: app/_src/.repos/kuma/jekyll-kuma-plugins
GIT
remote: https://github.com/kong/jekyll-generator-single-source.git
revision: 8e4e5e4bcd8d198b295454ee3bef5ec69a53c6e6
branch: i18n-spike
specs:
jekyll-kuma-plugins (0.1.0)
jekyll-generator-single-source (0.0.14)
i18n (~> 1)
jekyll (>= 4.2, < 5.0)

GEM
Expand Down Expand Up @@ -94,8 +97,6 @@ GEM
safe_yaml (~> 1.0)
terminal-table (>= 1.8, < 4.0)
webrick (~> 1.7)
jekyll-generator-single-source (0.0.14)
jekyll (>= 4.2, < 5.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-redirect-from (0.16.0)
Expand Down Expand Up @@ -224,10 +225,10 @@ DEPENDENCIES
activesupport
capybara
foreman
i18n
jekyll
jekyll-generator-single-source
jekyll-generator-single-source!
jekyll-include-cache
jekyll-kuma-plugins!
jekyll-redirect-from
jekyll-vite
kramdown-parser-gfm
Expand Down
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

vite: bin/vite dev
jekyll: bin/jekyll-vite wait && bundle exec jekyll serve --livereload --config jekyll-dev.yml --profile
jekyll: bin/jekyll-vite wait && bundle exec jekyll serve --livereload --config jekyll-dev.yml${JEKYLL_CONFIG_FILES:+,$JEKYLL_CONFIG_FILES} --profile
1 change: 0 additions & 1 deletion app/CNAME

This file was deleted.

1 change: 0 additions & 1 deletion app/_assets/entrypoints/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// When using a plain API, perhaps it's better to generate an HTML entrypoint
// and link to the scripts and stylesheets, and let Vite transform it.

import "~/javascripts/analytics.js";
import "~/javascripts/modal.js"
import "~/javascripts/app.js";
import "~/javascripts/compat-dropdown.js";
Expand Down
7 changes: 0 additions & 7 deletions app/_assets/javascripts/analytics.js

This file was deleted.

36 changes: 35 additions & 1 deletion app/_assets/javascripts/views/SearchApp/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@
</div>

<section class="search-container-results">

<KAlert
show-icon
v-if="pageI18n"
class="missing-translation-banner"
:message=pageI18n.banner
/>

<ais-hits :class-names="{ 'ais-Hits-item': 'card default' }" >
<template #item="{ item }">
<article class="hit">
Expand Down Expand Up @@ -154,6 +162,7 @@
</template>

<script>
import { ref } from 'vue'
import {
AisInstantSearch,
AisClearRefinements,
Expand All @@ -164,6 +173,9 @@ import {
AisPagination,
} from 'vue-instantsearch/vue3/es';
import { KAlert } from '@kong/kongponents'
import '@kong/kongponents/dist/style.css'
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import NoResults from './NoResults.vue';
import { routing } from './routing.js';
Expand All @@ -182,7 +194,14 @@ export default {
AisSearchBox,
AisHits,
AisPagination,
NoResults
NoResults,
KAlert
},
setup() {
const pageI18n = ref(window.pageI18n)
return {
pageI18n
}
},
data() {
return {
Expand Down Expand Up @@ -241,3 +260,18 @@ export default {
},
};
</script>

<style scoped>
.missing-translation-banner {
background-color: #f2f6fe !important;
border-left: solid 3px #3972d5;
color: inherit !important;
margin-bottom: 1em;
padding: 15px;
border-radius: 2px;
}
.missing-translation-banner :deep(.alert-icon-container) {
color: #3972d5;
}
</style>
8 changes: 8 additions & 0 deletions app/_assets/javascripts/views/SpecView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
</div>

<div class="spec-content">
<KAlert
show-icon
v-if="pageI18n"
class="deprecated-warning"
:message=pageI18n.banner
/>
<KAlert
v-if="deprecatedProductVersion"
appearance="warning"
Expand Down Expand Up @@ -53,6 +59,8 @@ const activeProductVersionId = ref(null);
const activeProductVersionName= ref(null);
const productIdParam = ref(window.oas.product.id);
const productVersionParam = ref(window.oas.version.id);
const pageI18n = ref(window.pageI18n);
const productsAPI = new ApiService().productsAPI;
const versionsAPI = new ApiService().versionsAPI;
const activeOperation = ref(null);
Expand Down
Loading

0 comments on commit 0fd492b

Please sign in to comment.