feat(i18n, client): migrate meta translations (#40885)
This commit is contained in:
committed by
GitHub
parent
f5f2df187b
commit
1a642ba542
@@ -14,10 +14,11 @@ i18n.use(initReactI18next).init({
|
||||
[i18nextCode]: {
|
||||
translations: require(`./locales/${clientLocale}/translations.json`),
|
||||
trending: require(`./locales/${clientLocale}/trending.json`),
|
||||
intro: require(`./locales/${clientLocale}/intro.json`)
|
||||
intro: require(`./locales/${clientLocale}/intro.json`),
|
||||
metaTags: require(`./locales/${clientLocale}/meta-tags.json`)
|
||||
}
|
||||
},
|
||||
ns: ['translations', 'trending', 'intro'],
|
||||
ns: ['translations', 'trending', 'intro', 'metaTags'],
|
||||
defaultNS: 'translations',
|
||||
returnObjects: true,
|
||||
// Uncomment the next line for debug logging
|
||||
|
@@ -23,6 +23,9 @@ const filesThatShouldExist = [
|
||||
},
|
||||
{
|
||||
name: 'intro.json'
|
||||
},
|
||||
{
|
||||
name: 'meta-tags.json'
|
||||
}
|
||||
];
|
||||
|
||||
|
27
client/i18n/locales/chinese/meta-tags.json
Normal file
27
client/i18n/locales/chinese/meta-tags.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"title": "免费学习编程 – 适合忙碌人士的编程课程",
|
||||
"description": "在家学习编程,构建项目,获得认证。自 2014 年以来,已有超过 40,000 名 freeCodeCamp 学员入职谷歌、苹果、亚马逊、微软等科技公司。",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"网站",
|
||||
"web",
|
||||
"开发",
|
||||
"free",
|
||||
"code",
|
||||
"camp",
|
||||
"课程",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"前端",
|
||||
"后端",
|
||||
"学习",
|
||||
"教程",
|
||||
"编程"
|
||||
],
|
||||
"youre-unsubscribed": "你已取消订阅"
|
||||
}
|
@@ -1,31 +1,4 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "免费学习编程 – 适合忙碌人士的编程课程",
|
||||
"description": "在家学习编程,构建项目,获得认证。自 2014 年以来,已有超过 40,000 名 freeCodeCamp 学员入职谷歌、苹果、亚马逊、微软等科技公司。",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"网站",
|
||||
"web",
|
||||
"开发",
|
||||
"free",
|
||||
"code",
|
||||
"camp",
|
||||
"课程",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"前端",
|
||||
"后端",
|
||||
"学习",
|
||||
"教程",
|
||||
"编程"
|
||||
],
|
||||
"youre-unsubscribed": "你已取消订阅"
|
||||
},
|
||||
"buttons": {
|
||||
"logged-in-cta-btn": "开始学习(免费)",
|
||||
"logged-out-cta-btn": "登录以保存你的学习进度(免费)",
|
||||
|
29
client/i18n/locales/english/meta-tags.json
Normal file
29
client/i18n/locales/english/meta-tags.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"title": "Learn to Code — For Free — Coding Courses for Busy People",
|
||||
"description": "Learn to Code — For Free",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"website",
|
||||
"web",
|
||||
"development",
|
||||
"free",
|
||||
"code",
|
||||
"camp",
|
||||
"course",
|
||||
"courses",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"front",
|
||||
"back",
|
||||
"end",
|
||||
"learn",
|
||||
"tutorial",
|
||||
"programming"
|
||||
],
|
||||
"youre-unsubscribed": "You have been unsubscribed"
|
||||
}
|
@@ -1,33 +1,4 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Learn to Code — For Free — Coding Courses for Busy People",
|
||||
"description": "Learn to Code — For Free",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"website",
|
||||
"web",
|
||||
"development",
|
||||
"free",
|
||||
"code",
|
||||
"camp",
|
||||
"course",
|
||||
"courses",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"front",
|
||||
"back",
|
||||
"end",
|
||||
"learn",
|
||||
"tutorial",
|
||||
"programming"
|
||||
],
|
||||
"youre-unsubscribed": "You have been unsubscribed"
|
||||
},
|
||||
"buttons": {
|
||||
"logged-in-cta-btn": "Get started (it's free)",
|
||||
"logged-out-cta-btn": "Sign in to save your progress (it's free)",
|
||||
|
29
client/i18n/locales/espanol/meta-tags.json
Normal file
29
client/i18n/locales/espanol/meta-tags.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"title": "Aprende a codificar gratis: cursos de programación para personas ocupadas",
|
||||
"description": "Aprende a codificar en casa. Construye proyectos. Obtén certificaciones. Desde el 2014, más de 40,000 graduados de freeCodeCamp.org han conseguido trabajos en empresas de tecnología como Google, Apple, Amazon y Microsoft.",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"sitio web",
|
||||
"web",
|
||||
"desarrollo",
|
||||
"gratis",
|
||||
"código",
|
||||
"camp",
|
||||
"curso",
|
||||
"cursos",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"front",
|
||||
"back",
|
||||
"end",
|
||||
"aprende",
|
||||
"tutorial",
|
||||
"programación"
|
||||
],
|
||||
"youre-unsubscribed": "Tu suscripción ha sido cancelada"
|
||||
}
|
@@ -1,33 +1,4 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Aprende a codificar gratis: cursos de programación para personas ocupadas",
|
||||
"description": "Aprende a codificar en casa. Construye proyectos. Obtén certificaciones. Desde el 2014, más de 40,000 graduados de freeCodeCamp.org han conseguido trabajos en empresas de tecnología como Google, Apple, Amazon y Microsoft.",
|
||||
"social-description": "Learn to Code — For Free",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"js",
|
||||
"sitio web",
|
||||
"web",
|
||||
"desarrollo",
|
||||
"gratis",
|
||||
"código",
|
||||
"camp",
|
||||
"curso",
|
||||
"cursos",
|
||||
"html",
|
||||
"css",
|
||||
"react",
|
||||
"redux",
|
||||
"api",
|
||||
"front",
|
||||
"back",
|
||||
"end",
|
||||
"aprende",
|
||||
"tutorial",
|
||||
"programación"
|
||||
],
|
||||
"youre-unsubscribed": "Tu suscripción ha sido cancelada"
|
||||
},
|
||||
"buttons": {
|
||||
"logged-in-cta-btn": "Empieza es gratis",
|
||||
"logged-out-cta-btn": "Inicia sesión para guardar tu progreso (es gratis)",
|
||||
|
31
client/i18n/meta-tags-schema.js
Normal file
31
client/i18n/meta-tags-schema.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const metaTagsSchema = {
|
||||
title: 'Learn to Code — For Free — Coding Courses for Busy People',
|
||||
description: 'Learn to Code — For Free',
|
||||
'social-description': 'Learn to Code — For Free',
|
||||
keywords: [
|
||||
'javascript',
|
||||
'js',
|
||||
'website',
|
||||
'web',
|
||||
'development',
|
||||
'free',
|
||||
'code',
|
||||
'camp',
|
||||
'course',
|
||||
'courses',
|
||||
'html',
|
||||
'css',
|
||||
'react',
|
||||
'redux',
|
||||
'api',
|
||||
'front',
|
||||
'back',
|
||||
'end',
|
||||
'learn',
|
||||
'tutorial',
|
||||
'programming'
|
||||
],
|
||||
'youre-unsubscribed': 'You have been unsubscribed'
|
||||
};
|
||||
|
||||
exports.metaTagsSchema = metaTagsSchema;
|
@@ -5,6 +5,7 @@ const { availableLangs } = require('./allLangs');
|
||||
const { trendingSchema } = require('./trending-schema');
|
||||
const { motivationSchema } = require('./motivation-schema');
|
||||
const { introSchema } = require('./intro-schema');
|
||||
const { metaTagsSchema } = require('./meta-tags-schema');
|
||||
|
||||
/**
|
||||
* Flattens a nested object structure into a single
|
||||
@@ -105,6 +106,7 @@ const translationSchemaKeys = Object.keys(flattenAnObject(translationsSchema));
|
||||
const trendingSchemaKeys = Object.keys(flattenAnObject(trendingSchema));
|
||||
const motivationSchemaKeys = Object.keys(flattenAnObject(motivationSchema));
|
||||
const introSchemaKeys = Object.keys(flattenAnObject(introSchema));
|
||||
const metaTagsSchemaKeys = Object.keys(flattenAnObject(metaTagsSchema));
|
||||
|
||||
/**
|
||||
* Function that checks the translations.json file
|
||||
@@ -236,7 +238,35 @@ const introSchemaValidation = languages => {
|
||||
});
|
||||
};
|
||||
|
||||
const metaTagsSchemaValidation = languages => {
|
||||
languages.forEach(language => {
|
||||
const filePath = path.join(
|
||||
__dirname,
|
||||
`/locales/${language}/meta-tags.json`
|
||||
);
|
||||
const fileData = fs.readFileSync(filePath);
|
||||
const fileJson = JSON.parse(fileData);
|
||||
const fileKeys = Object.keys(flattenAnObject(fileJson));
|
||||
findMissingKeys(fileKeys, metaTagsSchemaKeys, `${language}/meta-tags.json`);
|
||||
findExtraneousKeys(
|
||||
fileKeys,
|
||||
metaTagsSchemaKeys,
|
||||
`${language}/metaTags.json`
|
||||
);
|
||||
const emptyKeys = noEmptyObjectValues(fileJson);
|
||||
if (emptyKeys.length) {
|
||||
throw new Error(
|
||||
`${language}/metaTags.json has these empty keys: ${emptyKeys.join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
}
|
||||
console.info(`${language} metaTags.json is correct!`);
|
||||
});
|
||||
};
|
||||
|
||||
translationSchemaValidation(availableLangs.client);
|
||||
trendingSchemaValidation(availableLangs.client);
|
||||
motivationSchemaValidation(availableLangs.client);
|
||||
introSchemaValidation(availableLangs.client);
|
||||
metaTagsSchemaValidation(availableLangs.client);
|
||||
|
@@ -3,35 +3,6 @@
|
||||
* structure here exactly, the tests will fail.
|
||||
*/
|
||||
const translationsSchema = {
|
||||
meta: {
|
||||
title: 'Learn to Code — For Free — Coding Courses for Busy People',
|
||||
description: 'Learn to Code — For Free',
|
||||
'social-description': 'Learn to Code — For Free',
|
||||
keywords: [
|
||||
'javascript',
|
||||
'js',
|
||||
'website',
|
||||
'web',
|
||||
'development',
|
||||
'free',
|
||||
'code',
|
||||
'camp',
|
||||
'course',
|
||||
'courses',
|
||||
'html',
|
||||
'css',
|
||||
'react',
|
||||
'redux',
|
||||
'api',
|
||||
'front',
|
||||
'back',
|
||||
'end',
|
||||
'learn',
|
||||
'tutorial',
|
||||
'programming'
|
||||
],
|
||||
'youre-unsubscribed': 'You have been unsubscribed'
|
||||
},
|
||||
buttons: {
|
||||
'logged-in-cta-btn': "Get started (it's free)",
|
||||
'logged-out-cta-btn': "Sign in to save your progress (it's free)",
|
||||
|
@@ -15,7 +15,7 @@ function ShowUnsubscribed({ unsubscribeId }) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Helmet>
|
||||
<title>{t('meta.youre-unsubscribed')} | freeCodeCamp.org</title>
|
||||
<title>{t('metaTags:youre-unsubscribed')} | freeCodeCamp.org</title>
|
||||
</Helmet>
|
||||
<Grid>
|
||||
<main>
|
||||
|
@@ -21,7 +21,7 @@ export const Landing = ({ page = 'landing' }) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Helmet>
|
||||
<title>{t('meta.title')}</title>
|
||||
<title>{t('metaTags:title')}</title>
|
||||
</Helmet>
|
||||
<main className='landing-page'>
|
||||
<Grid>
|
||||
|
@@ -152,9 +152,9 @@ class DefaultLayout extends Component {
|
||||
meta={[
|
||||
{
|
||||
name: 'description',
|
||||
content: t('meta.description')
|
||||
content: t('metaTags:description')
|
||||
},
|
||||
{ name: 'keywords', content: t('meta.keywords') }
|
||||
{ name: 'keywords', content: t('metaTags:keywords') }
|
||||
]}
|
||||
>
|
||||
<link
|
||||
|
@@ -61,7 +61,7 @@ export const LearnPage = ({
|
||||
|
||||
return (
|
||||
<LearnLayout>
|
||||
<Helmet title={t('meta.title')} />
|
||||
<Helmet title={t('metaTags:title')} />
|
||||
<Grid>
|
||||
<Row>
|
||||
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
||||
|
@@ -16,7 +16,7 @@ export const getheadTagComponents = () => {
|
||||
<link href={pathToBootstrap} key='bootstrap-min' rel='stylesheet' />,
|
||||
<meta content='freeCodeCamp.org' key='og:title' name='og:title' />,
|
||||
<meta
|
||||
content={i18next.t('meta.social-description')}
|
||||
content={i18next.t('metaTags:social-description')}
|
||||
key='og:description'
|
||||
name='og:description'
|
||||
/>,
|
||||
@@ -37,7 +37,7 @@ export const getheadTagComponents = () => {
|
||||
name='twitter:title'
|
||||
/>,
|
||||
<meta
|
||||
content={i18next.t('meta.social-description')}
|
||||
content={i18next.t('metaTags:social-description')}
|
||||
key='twitter:description'
|
||||
name='twitter:description'
|
||||
/>,
|
||||
|
Reference in New Issue
Block a user