mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-01 10:22:30 +02:00
Fix: conflicting strings issue in translations (#917)
* Fix conflicting strings issue in translations * Preserve structure of `customTranslations` * Use `deepmerge` to merge whole of `localized-strings` * Simplify and make deep property access on an object safe * Fix deep property accessor and rename it to idx
This commit is contained in:
parent
d18b09954b
commit
cfabaedc99
12 changed files with 94 additions and 66 deletions
|
@ -16,6 +16,7 @@ const DocsSidebar = require('./DocsSidebar.js');
|
|||
const OnPageNav = require('./nav/OnPageNav.js');
|
||||
const Site = require('./Site.js');
|
||||
const translation = require('../server/translation.js');
|
||||
const {idx} = require('./utils.js');
|
||||
|
||||
// component used to generate whole webpage for docs, including sidebar/header/footer
|
||||
class DocsLayout extends React.Component {
|
||||
|
@ -35,16 +36,15 @@ class DocsLayout extends React.Component {
|
|||
render() {
|
||||
const metadata = this.props.metadata;
|
||||
const content = this.props.children;
|
||||
const i18n = translation[this.props.metadata.language];
|
||||
const i18n = translation[metadata.language];
|
||||
const id = metadata.localized_id;
|
||||
const defaultTitle = metadata.title;
|
||||
let DocComponent = Doc;
|
||||
if (this.props.Doc) {
|
||||
DocComponent = this.props.Doc;
|
||||
}
|
||||
const title = i18n
|
||||
? translation[this.props.metadata.language]['localized-strings'][
|
||||
this.props.metadata.localized_id
|
||||
] || this.props.metadata.title
|
||||
: this.props.metadata.title;
|
||||
const title =
|
||||
idx(i18n, ['localized-strings', 'docs', id, 'title']) || defaultTitle;
|
||||
const hasOnPageNav = this.props.config.onPageNav === 'separate';
|
||||
return (
|
||||
<Site
|
||||
|
@ -65,7 +65,7 @@ class DocsLayout extends React.Component {
|
|||
content={content}
|
||||
config={this.props.config}
|
||||
source={metadata.source}
|
||||
hideTitle={this.props.metadata.hide_title}
|
||||
hideTitle={metadata.hide_title}
|
||||
title={title}
|
||||
version={metadata.version}
|
||||
language={metadata.language}
|
||||
|
@ -79,15 +79,10 @@ class DocsLayout extends React.Component {
|
|||
metadata.previous_id
|
||||
)}>
|
||||
←{' '}
|
||||
{i18n
|
||||
? translation[this.props.metadata.language][
|
||||
'localized-strings'
|
||||
][metadata.previous_id] ||
|
||||
translation[this.props.metadata.language][
|
||||
'localized-strings'
|
||||
].previous ||
|
||||
'Previous'
|
||||
: metadata.previous_title || 'Previous'}
|
||||
{idx(i18n, ['localized-strings', metadata.previous_id]) ||
|
||||
idx(i18n, ['localized-strings', 'previous']) ||
|
||||
metadata.previous_title ||
|
||||
'Previous'}
|
||||
</a>
|
||||
)}
|
||||
{metadata.next_id && (
|
||||
|
@ -97,15 +92,10 @@ class DocsLayout extends React.Component {
|
|||
metadata.localized_id,
|
||||
metadata.next_id
|
||||
)}>
|
||||
{i18n
|
||||
? translation[this.props.metadata.language][
|
||||
'localized-strings'
|
||||
][metadata.next_id] ||
|
||||
translation[this.props.metadata.language][
|
||||
'localized-strings'
|
||||
].next ||
|
||||
'Next'
|
||||
: metadata.next_title || 'Next'}{' '}
|
||||
{idx(i18n, ['localized-strings', metadata.next_id]) ||
|
||||
idx(i18n, ['localized-strings', 'next']) ||
|
||||
metadata.next_title ||
|
||||
'Next'}{' '}
|
||||
→
|
||||
</a>
|
||||
)}
|
||||
|
@ -113,7 +103,7 @@ class DocsLayout extends React.Component {
|
|||
</Container>
|
||||
{hasOnPageNav && (
|
||||
<nav className="onPageNav">
|
||||
<OnPageNav rawContent={this.props.children} />
|
||||
<OnPageNav rawContent={content} />
|
||||
</nav>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
const React = require('react');
|
||||
const Head = require('./Head.js');
|
||||
const translation = require('../server/translation.js');
|
||||
const {idx} = require('./utils.js');
|
||||
|
||||
// Component used to provide same head, header, footer, other scripts to all pages
|
||||
class Redirect extends React.Component {
|
||||
render() {
|
||||
const tagline = translation[this.props.language]
|
||||
? translation[this.props.language]['localized-strings'].tagline
|
||||
: this.props.config.tagline;
|
||||
const tagline =
|
||||
idx(translation, [this.props.language, 'localized-strings', 'tagline']) ||
|
||||
this.props.config.tagline;
|
||||
const title = this.props.title
|
||||
? `${this.props.title} · ${this.props.config.title}`
|
||||
: (!this.props.config.disableTitleTagline &&
|
||||
|
|
|
@ -14,15 +14,16 @@ const Head = require('./Head.js');
|
|||
const Footer = require(`${process.cwd()}/core/Footer.js`);
|
||||
const translation = require('../server/translation.js');
|
||||
const constants = require('./constants');
|
||||
const {idx} = require('./utils.js');
|
||||
|
||||
const CWD = process.cwd();
|
||||
|
||||
// Component used to provide same head, header, footer, other scripts to all pages
|
||||
class Site extends React.Component {
|
||||
render() {
|
||||
const tagline = translation[this.props.language]
|
||||
? translation[this.props.language]['localized-strings'].tagline
|
||||
: this.props.config.tagline;
|
||||
const tagline =
|
||||
idx(translation, [this.props.language, 'localized-strings', 'tagline']) ||
|
||||
this.props.config.tagline;
|
||||
const title = this.props.title
|
||||
? `${this.props.title} · ${this.props.config.title}`
|
||||
: (!this.props.config.disableTitleTagline &&
|
||||
|
|
|
@ -22,7 +22,7 @@ const readMetadata = require('../../server/readMetadata.js');
|
|||
|
||||
readMetadata.generateMetadataDocs();
|
||||
const Metadata = require('../metadata.js');
|
||||
const utils = require('../utils.js');
|
||||
const {idx, getPath} = require('../utils.js');
|
||||
|
||||
const extension = siteConfig.cleanUrl ? '' : '.html';
|
||||
|
||||
|
@ -56,7 +56,7 @@ class LanguageDropDown extends React.Component {
|
|||
}
|
||||
return (
|
||||
<li key={lang.tag}>
|
||||
<a href={utils.getPath(href, this.props.cleanUrl)}>{lang.name}</a>
|
||||
<a href={getPath(href, this.props.cleanUrl)}>{lang.name}</a>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
@ -188,7 +188,7 @@ class HeaderNav extends React.Component {
|
|||
}
|
||||
href =
|
||||
this.props.config.baseUrl +
|
||||
utils.getPath(Metadata[id].permalink, this.props.config.cleanUrl);
|
||||
getPath(Metadata[id].permalink, this.props.config.cleanUrl);
|
||||
|
||||
const {id: currentID, sidebar} = this.props.current;
|
||||
docItemActive = currentID && currentID === id;
|
||||
|
@ -220,12 +220,11 @@ class HeaderNav extends React.Component {
|
|||
(link.blog && this.props.current.blogListing) ||
|
||||
(link.page && link.page === this.props.current.id),
|
||||
});
|
||||
const i18n = translation[this.props.language];
|
||||
return (
|
||||
<li key={`${link.label}page`} className={itemClasses}>
|
||||
<a href={href} target={link.external ? '_blank' : '_self'}>
|
||||
{translation[this.props.language]
|
||||
? translation[this.props.language]['localized-strings'][link.label]
|
||||
: link.label}
|
||||
{idx(i18n, ['localized-strings', 'links', link.label]) || link.label}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
|
|
|
@ -10,15 +10,18 @@ const classNames = require('classnames');
|
|||
|
||||
const siteConfig = require(`${process.cwd()}/siteConfig.js`);
|
||||
const translation = require('../../server/translation.js');
|
||||
const utils = require('../utils.js');
|
||||
const {getPath, idx} = require('../utils.js');
|
||||
|
||||
class SideNav extends React.Component {
|
||||
// return appropriately translated category string
|
||||
getLocalizedCategoryString(category) {
|
||||
const categoryString = translation[this.props.language]
|
||||
? translation[this.props.language]['localized-strings'][category] ||
|
||||
category
|
||||
: category;
|
||||
const categoryString =
|
||||
idx(translation, [
|
||||
this.props.language,
|
||||
'localized-strings',
|
||||
'categories',
|
||||
category,
|
||||
]) || category;
|
||||
return categoryString;
|
||||
}
|
||||
|
||||
|
@ -26,17 +29,16 @@ class SideNav extends React.Component {
|
|||
getLocalizedString(metadata) {
|
||||
let localizedString;
|
||||
const i18n = translation[this.props.language];
|
||||
const id = metadata.localized_id;
|
||||
const sbTitle = metadata.sidebar_label;
|
||||
|
||||
if (sbTitle) {
|
||||
localizedString = i18n
|
||||
? i18n['localized-strings'][sbTitle] || sbTitle
|
||||
: sbTitle;
|
||||
localizedString =
|
||||
idx(i18n, ['localized-strings', 'docs', id, 'sidebar_label']) ||
|
||||
sbTitle;
|
||||
} else {
|
||||
const id = metadata.original_id || metadata.localized_id;
|
||||
localizedString = i18n
|
||||
? i18n['localized-strings'][id] || metadata.title
|
||||
: metadata.title;
|
||||
localizedString =
|
||||
idx(i18n, ['localized-strings', 'docs', id, 'title']) || metadata.title;
|
||||
}
|
||||
return localizedString;
|
||||
}
|
||||
|
@ -44,14 +46,14 @@ class SideNav extends React.Component {
|
|||
// return link to doc in sidebar
|
||||
getLink(metadata) {
|
||||
if (metadata.permalink) {
|
||||
const targetLink = utils.getPath(metadata.permalink, siteConfig.cleanUrl);
|
||||
const targetLink = getPath(metadata.permalink, siteConfig.cleanUrl);
|
||||
if (targetLink.match(/^https?:/)) {
|
||||
return targetLink;
|
||||
}
|
||||
return siteConfig.baseUrl + targetLink;
|
||||
}
|
||||
if (metadata.path) {
|
||||
return `${siteConfig.baseUrl}blog/${utils.getPath(
|
||||
return `${siteConfig.baseUrl}blog/${getPath(
|
||||
metadata.path,
|
||||
siteConfig.cleanUrl
|
||||
)}`;
|
||||
|
|
|
@ -28,9 +28,14 @@ function getPath(pathStr, cleanUrl = false) {
|
|||
: removeExtension(pathStr);
|
||||
}
|
||||
|
||||
function idx(target, path) {
|
||||
return path.reduce((obj, key) => obj && obj[key], target);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
blogPostHasTruncateMarker,
|
||||
extractBlogPostBeforeTruncate,
|
||||
getPath,
|
||||
removeExtension,
|
||||
idx,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue