Skip to content

Feat/poc translate by json - POC - NOT MERGE #1738

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

Closed
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
3 changes: 3 additions & 0 deletions _includes/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<link rel="stylesheet" href="/css/font-awesome.min.css">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;amp;subset=latin,latin-ext">
<link rel="stylesheet" href="/css/{{ page.lang }}.css">
<script src="/assets/js/translations.js"></script>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="description" content="{{page.description}}">
Expand Down Expand Up @@ -48,3 +49,5 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />

</head>

<html lang="{{ page.lang | default: 'en' }}">
166 changes: 166 additions & 0 deletions _includes/header/header.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<header>
<div id="mobile-menu">
<div id="nav-button" class="fa fa-bars fa-2x button"></div>
</div>
<section id="logo"><a href="/" class="express">Express</a>
</section>
<div id="navbar">
<input id="q" placeholder="🔎 search">
<ul id="navmenu">
<li><a href="/" id="home-menu"{% if page.menu == 'home' %} class="active"{% endif %}><span data-i18n="header_home">Home</span></a></li>
<li id="getting-started-menu" class="submenu">
<a href="/{{ page.lang }}/starter/installing.html"{% if page.menu == 'starter' %} class="active"{% endif %}>
<span data-i18n="getting_started">Getting started</span>
</a>
<ul class="submenu-content">
<li>
<a href="/{{ page.lang }}/starter/installing.html">
Installing
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/hello-world.html">
Hello world
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/generator.html">
Express generator
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/basic-routing.html">
Basic routing
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/static-files.html">
Static files
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/examples.html">
More examples
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/faq.html">
FAQ
</a>
</li>
</ul>
</li>
<li id="guide-menu" class="submenu">
<a href="/{{ page.lang }}/guide/routing.html"{% if page.menu == 'guide' %} class="active"{% endif %}>
<span data-i18n="guide">Guide</span>
</a>
<ul class="submenu-content">
<li><a href="/{{ page.lang }}/guide/routing.html">Routing</a>
</li>
<li><a href="/{{ page.lang }}/guide/writing-middleware.html">Writing middleware</a>
</li>
<li><a href="/{{ page.lang }}/guide/using-middleware.html">Using middleware</a>
</li>
<li><a href="/{{ page.lang }}/guide/overriding-express-api.html">Overriding the Express API</a>
</li>
<li><a href="/{{ page.lang }}/guide/using-template-engines.html">Using template engines</a>
</li>
<li><a href="/{{ page.lang }}/guide/error-handling.html">Error handling</a>
</li>
<li><a href="/{{ page.lang }}/guide/debugging.html">Debugging</a>
</li>
<li><a href="/{{ page.lang }}/guide/behind-proxies.html">Express behind proxies</a>
</li>
<li><a href="/{{ page.lang }}/guide/migrating-4.html">Moving to Express 4</a>
</li>
<li><a href="/{{ page.lang }}/guide/migrating-5.html">Moving to Express 5</a>
</li>
<li><a href="/{{ page.lang }}/guide/database-integration.html">Database integration</a>
</li>
</ul>
</li>
<li id="application-menu" class="submenu">
<a href="/{{ page.lang }}/5x/api.html"{% if page.menu == 'api' %} class="active"{% endif %}>
<span data-i18n="api_reference">API reference</span>
</a>
<ul class="submenu-content">
<li><a href="/{{ page.lang }}/5x/api.html">5.x</a>
</li>
<li><a href="/{{ page.lang }}/4x/api.html">4.x</a>
</li>
<li><a href="/{{ page.lang }}/3x/api.html">3.x (deprecated)</a>
</li>
<li><a href="/2x/">2.x (deprecated)</a>
</li>
</ul>
</li>
<li id="advanced-topics-menu" class="submenu">
<a href="/{{ page.lang }}/advanced/developing-template-engines.html"{% if page.menu == 'advanced' %} class="active"{% endif %}>
<span data-i18n="advanced_topics">Advanced topics</span>
</a>
<ul class="submenu-content">
<li><a href="/{{ page.lang }}/advanced/developing-template-engines.html">Building template engines</a>
</li>
<li><a href="/{{ page.lang }}/advanced/security-updates.html">Security updates</a>
</li>
<li><a href="/{{ page.lang }}/advanced/best-practice-security.html">Security best practices</a>
</li>
<li><a href="/{{ page.lang }}/advanced/best-practice-performance.html">Performance best practices</a>
</li>
<li><a href="/{{ page.lang }}/advanced/healthcheck-graceful-shutdown.html">Health checks & shutdown</a>
</li>
</ul>
</li>
<li id="resources-menu" class="submenu">
<a href="/{{ page.lang }}/resources/glossary.html"{% if page.menu == 'resources' %} class="active"{% endif %}>
<span data-i18n="resources">Resources</span>
</a>
<ul class="submenu-content">
<li>
<a href="/{{ page.lang }}/resources/community.html">Community</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/glossary.html">Glossary</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/middleware.html">Middleware</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/utils.html">Utility modules</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/contributing.html">Contributing to Express</a>
</li>
<li>
<a href="/{{ page.lang }}/changelog/4x.html">Release Change Log</a>
</li>
</ul>
</li>
<li>
<a href="/{{ page.lang }}/support" id="support-menu"{% if page.menu == 'support' %} class="active"{% endif %}>
<span data-i18n="support">Support</span>
</a>
</li>
<li id="blog-menu" class="submenu">
<a href="{{site.posts.first.url}}"{% if page.menu == 'blog' %} class="active"{% endif %}>
<span data-i18n="blog">Blog</span>
</a>
<ul class="submenu-content">
<li>
<a href="{{site.posts.first.url}}">Latest post</a>
</li>
<li>
<a href="/{{ page.lang }}/blog/posts.html">All posts</a>
</li>
<li>
<a href="/{{ page.lang }}/blog/write-post.html">Write a Post</a>
</li>
</ul>
</li>
</ul>
</div>
<div id="theme-icon-container" class="theme-toggle default-theme" title="toggle darkmode">
<i class="fa fa-moon-o fa-2x hidden-dark"></i>
<span class="sun-icon hidden-light"></span>
</div>
</header>
2 changes: 1 addition & 1 deletion _layouts/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<section class="page content">

{% include header/header-{{ page.lang }}.html %}
{% include header/header.html %}

<div id="overlay"></div>

Expand Down
45 changes: 45 additions & 0 deletions assets/js/translations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function loadTranslations() {
// Get language from page.lang, fallback to 'en' if not set
const currentLang = document.documentElement.getAttribute('lang') || 'en';
const lang = currentLang.toLowerCase().includes('pt') ? 'pt-br' :
currentLang.toLowerCase().includes('es') ? 'es' : 'en';

// List of JSON files in i18n directory
const translationFiles = [
'/i18n/home.json',
'/i18n/header.json'
// Add new JSON files here automatically using server-side logic
];

// Load all translation files
Promise.all(
translationFiles.map(file =>
fetch(file)
.then(response => response.json())
.catch(error => {
console.error(`Error loading ${file}:`, error);
return {}; // Return empty object if file fails to load
})
)
)
.then(results => {
// Merge all translations from all files
const translations = results.reduce((acc, data) => {
return {
...acc,
...(data[lang] || data['en'])
};
}, {});

// Apply translations
document.querySelectorAll('[data-i18n]').forEach(element => {
const key = element.getAttribute('data-i18n');
if (translations[key]) {
element.textContent = translations[key];
}
});
})
.catch(error => console.error('Error loading translations:', error));
}

document.addEventListener('DOMContentLoaded', loadTranslations);
11 changes: 11 additions & 0 deletions i18n/header.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"en": {
"header_home": "Home (translate en)"
},
"pt-br": {
"header_home": "Início (translate pt-br)"
},
"es": {
"header_home": "Inicio (translate es)"
}
}
11 changes: 11 additions & 0 deletions i18n/home.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"en": {
"home_description": "Fast, unopinionated, minimalist web framework for (translate en)"
},
"pt-br": {
"home_description": "Infraestrutura web rápida, minimalista e flexível para (translate pt-br) "
},
"es": {
"home_description": "Infraestructura web rápida, minimalista y flexible para (translate es)"
}
}
2 changes: 1 addition & 1 deletion index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ redirect_from: "/en/index.html"
<div id="homepage-leftpane" class="pane">
<section id="description">
<div class="express"><a href="/">Express</a><a href="{{ page.lang }}/changelog/4x.html#{{ site.data.express.current_version }}" id="express-version">{{ site.data.express.current_version }}</a></div>
<span class="description">Fast, unopinionated, minimalist web framework for <a href='https://nodejs.org/en/'>Node.js</a></span>
<span class="description" data-i18n="home_description">Fast, unopinionated, minimalist web framework for <a href='https://nodejs.org/en/'>Node.js</a></span>
</section>
<div id="install-command">$ npm install express --save</div>
</div>
Expand Down
Loading