Add react-i18next for multi-language support (#917)

This is a rough start on adding react-i18next. I'll be working on adding
more translatable strings and translations in the coming days. I'm going
to need to wrap class components in HOCs, so let me know if there's
something I should be fixing before doing that. I'm thinking now to keep
the exported class names exactly the same, and rename the existing
classes by prefixing an `I` (for internal). For example:

```
export default class AppToolbar ...
```

becomes

```
class IAppToolbar ...
const AppToolbar = withTranslation()(IAppToolbar);
export default AppToolbar;
```

I'll be able to contribute Japanese strings (I've talked to a couple
people on my team and they'll be happy to help as well), so that's the
language I decided to go with in this PR.

Closes #746

---------

Co-authored-by: Ko Nagase <nagase@georepublic.co.jp>
Co-authored-by: Harel M <harel.mazor@gmail.com>
This commit is contained in:
Keitaroh Kobayashi
2024-08-19 18:43:04 +09:00
committed by GitHub
parent 35840409b8
commit 58edd262b0
55 changed files with 2333 additions and 501 deletions
+33 -29
View File
@@ -1,6 +1,7 @@
import React from 'react'
import latest from '@maplibre/maplibre-gl-style-spec/dist/latest.json'
import type {LightSpecification, StyleSpecification, TerrainSpecification, TransitionSpecification} from 'maplibre-gl'
import { WithTranslation, withTranslation } from 'react-i18next';
import FieldArray from './FieldArray'
import FieldNumber from './FieldNumber'
@@ -12,15 +13,15 @@ import FieldColor from './FieldColor'
import Modal from './Modal'
import fieldSpecAdditional from '../libs/field-spec-additional'
type ModalSettingsProps = {
type ModalSettingsInternalProps = {
mapStyle: StyleSpecification
onStyleChanged(...args: unknown[]): unknown
onChangeMetadataProperty(...args: unknown[]): unknown
isOpen: boolean
onOpenToggle(...args: unknown[]): unknown
};
} & WithTranslation;
export default class ModalSettings extends React.Component<ModalSettingsProps> {
class ModalSettingsInternal extends React.Component<ModalSettingsInternalProps> {
changeTransitionProperty(property: keyof TransitionSpecification, value: number | undefined) {
const transition = {
...this.props.mapStyle.transition,
@@ -95,7 +96,8 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
render() {
const metadata = this.props.mapStyle.metadata || {} as any;
const {onChangeMetadataProperty, mapStyle} = this.props;
const {t, onChangeMetadataProperty, mapStyle} = this.props;
const fsa = fieldSpecAdditional(t);
const light = this.props.mapStyle.light || {};
const transition = this.props.mapStyle.transition || {};
@@ -105,33 +107,33 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
data-wd-key="modal:settings"
isOpen={this.props.isOpen}
onOpenToggle={this.props.onOpenToggle}
title={'Style Settings'}
title={t('Style Settings')}
>
<div className="modal:settings">
<FieldString
label={"Name"}
label={t("Name")}
fieldSpec={latest.$root.name}
data-wd-key="modal:settings.name"
value={this.props.mapStyle.name}
onChange={this.changeStyleProperty.bind(this, "name")}
/>
<FieldString
label={"Owner"}
fieldSpec={{doc: "Owner ID of the style. Used by Mapbox or future style APIs."}}
label={t("Owner")}
fieldSpec={{doc: t("Owner ID of the style. Used by Mapbox or future style APIs.")}}
data-wd-key="modal:settings.owner"
value={(this.props.mapStyle as any).owner}
onChange={this.changeStyleProperty.bind(this, "owner")}
/>
<FieldUrl
fieldSpec={latest.$root.sprite}
label="Sprite URL"
label={t("Sprite URL")}
data-wd-key="modal:settings.sprite"
value={this.props.mapStyle.sprite as string}
onChange={this.changeStyleProperty.bind(this, "sprite")}
/>
<FieldUrl
label="Glyphs URL"
label={t("Glyphs URL")}
fieldSpec={latest.$root.glyphs}
data-wd-key="modal:settings.glyphs"
value={this.props.mapStyle.glyphs as string}
@@ -139,23 +141,23 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldString
label={fieldSpecAdditional.maputnik.maptiler_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.maptiler_access_token}
label={fsa.maputnik.maptiler_access_token.label}
fieldSpec={fsa.maputnik.maptiler_access_token}
data-wd-key="modal:settings.maputnik:openmaptiles_access_token"
value={metadata['maputnik:openmaptiles_access_token']}
onChange={onChangeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
/>
<FieldString
label={fieldSpecAdditional.maputnik.thunderforest_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.thunderforest_access_token}
label={fsa.maputnik.thunderforest_access_token.label}
fieldSpec={fsa.maputnik.thunderforest_access_token}
data-wd-key="modal:settings.maputnik:thunderforest_access_token"
value={metadata['maputnik:thunderforest_access_token']}
onChange={onChangeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
/>
<FieldArray
label={"Center"}
label={t("Center")}
fieldSpec={latest.$root.center}
length={2}
type="number"
@@ -165,7 +167,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Zoom"}
label={t("Zoom")}
fieldSpec={latest.$root.zoom}
value={mapStyle.zoom}
default={0}
@@ -173,7 +175,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Bearing"}
label={t("Bearing")}
fieldSpec={latest.$root.bearing}
value={mapStyle.bearing}
default={latest.$root.bearing.default}
@@ -181,7 +183,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Pitch"}
label={t("Pitch")}
fieldSpec={latest.$root.pitch}
value={mapStyle.pitch}
default={latest.$root.pitch.default}
@@ -189,7 +191,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldEnum
label={"Light anchor"}
label={t("Light anchor")}
fieldSpec={latest.light.anchor}
name="light-anchor"
value={light.anchor as string}
@@ -199,7 +201,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldColor
label={"Light color"}
label={t("Light color")}
fieldSpec={latest.light.color}
value={light.color as string}
default={latest.light.color.default}
@@ -207,7 +209,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Light intensity"}
label={t("Light intensity")}
fieldSpec={latest.light.intensity}
value={light.intensity as number}
default={latest.light.intensity.default}
@@ -215,7 +217,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldArray
label={"Light position"}
label={t("Light position")}
fieldSpec={latest.light.position}
type="number"
length={latest.light.position.length}
@@ -225,7 +227,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldString
label={"Terrain source"}
label={t("Terrain source")}
fieldSpec={latest.terrain.source}
data-wd-key="modal:settings.maputnik:terrain_source"
value={terrain.source}
@@ -233,7 +235,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Terrain exaggeration"}
label={t("Terrain exaggeration")}
fieldSpec={latest.terrain.exaggeration}
value={terrain.exaggeration}
default={latest.terrain.exaggeration.default}
@@ -241,7 +243,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Transition delay"}
label={t("Transition delay")}
fieldSpec={latest.transition.delay}
value={transition.delay}
default={latest.transition.delay.default}
@@ -249,7 +251,7 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldNumber
label={"Transition duration"}
label={t("Transition duration")}
fieldSpec={latest.transition.duration}
value={transition.duration}
default={latest.transition.duration.default}
@@ -257,12 +259,12 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
/>
<FieldSelect
label={fieldSpecAdditional.maputnik.style_renderer.label}
fieldSpec={fieldSpecAdditional.maputnik.style_renderer}
label={fsa.maputnik.style_renderer.label}
fieldSpec={fsa.maputnik.style_renderer}
data-wd-key="modal:settings.maputnik:renderer"
options={[
['mlgljs', 'MapLibreGL JS'],
['ol', 'Open Layers (experimental)'],
['ol', t('Open Layers (experimental)')],
]}
value={metadata['maputnik:renderer'] || 'mlgljs'}
onChange={onChangeMetadataProperty.bind(this, 'maputnik:renderer')}
@@ -272,3 +274,5 @@ export default class ModalSettings extends React.Component<ModalSettingsProps> {
}
}
const ModalSettings = withTranslation()(ModalSettingsInternal)
export default ModalSettings;