IndexPage/Pagination/VersionSelector are now translated into Polish and English

This commit is contained in:
Dawid Wysokiński 2020-11-05 05:58:18 +01:00
parent cde80bd092
commit 7360dc9554
15 changed files with 163 additions and 21 deletions

View File

@ -1,4 +1,6 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { COMMON } from '@config/namespaces';
import {
Pagination as MaterialUIPagination,
@ -11,10 +13,31 @@ export type Props = PaginationProps & {
};
function Pagination({ total, perPage, ...rest }: Props) {
const { t } = useTranslation(COMMON);
const getItemAriaLabel = (
type: 'page' | 'first' | 'last' | 'next' | 'previous',
page: number
): string => {
switch (type) {
case 'page':
return `${t<string>('pagination.page')} ${page}`;
case 'first':
return t<string>('pagination.first');
case 'last':
return t<string>('pagination.last');
case 'next':
return t<string>('pagination.next');
case 'previous':
return t<string>('pagination.previous');
}
return '';
};
if (total && perPage) {
rest.count = total > 0 ? Math.ceil(total / perPage) : 1;
}
return <MaterialUIPagination {...rest} />;
return <MaterialUIPagination {...rest} getItemAriaLabel={getItemAriaLabel} />;
}
export default Pagination;

View File

@ -1,22 +1,24 @@
import React, { useState } from 'react';
import { useQuery } from '@apollo/client';
import { useTranslation } from 'react-i18next';
import { COMMON } from '@config/namespaces';
import { LANG_VERSIONS } from './queries';
import { LangVersionList } from './types';
import extractLangTagFromHostname from '@utils/extractLangTagFromHostname';
import useStyles from './styles';
import { Button, Menu, MenuItem, Link } from '@material-ui/core';
import { Button, Menu, MenuItem, Link, Tooltip } from '@material-ui/core';
import { Language as LanguageIcon } from '@material-ui/icons';
function VersionSelector() {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const { t } = useTranslation(COMMON);
const langTag = extractLangTagFromHostname(window.location.hostname);
const classes = useStyles();
const { data, loading } = useQuery<LangVersionList>(LANG_VERSIONS, {
fetchPolicy: 'cache-first',
variables: {
filter: {
sort: 'tag ASC',
tagNEQ: [langTag],
},
},
});
@ -41,12 +43,17 @@ function VersionSelector() {
return (
<div>
<Button
startIcon={<LanguageIcon />}
onClick={loading ? undefined : handleClick}
<Tooltip
title={t<string>('versionSelector.changeVersion')}
placement="bottom"
>
{langTag}
</Button>
<Button
startIcon={<LanguageIcon />}
onClick={loading ? undefined : handleClick}
>
{langTag}
</Button>
</Tooltip>
<Menu
anchorEl={anchorEl}
keepMounted
@ -58,11 +65,11 @@ function VersionSelector() {
<MenuItem
component={Link}
href={buildLink(lv.tag)}
className={classes.menuItem}
underline="none"
key={lv.tag}
title={lv.host}
>
{lv.tag}
{lv.host}
</MenuItem>
);
})}

View File

@ -5,6 +5,7 @@ export const LANG_VERSIONS = gql`
langVersions(filter: $filter) {
items {
tag
host
}
}
}

View File

@ -2,6 +2,7 @@ import { List } from '@libs/graphql/types';
export type LangVersion = {
tag: string;
host: string;
};
export type LangVersionList = {

View File

@ -1,4 +1,4 @@
export const DEFAULT_LANGUAGE = 'en';
export const DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE ?? 'en';
export const SERVER_STATUS = {
CLOSED: 'closed',

2
src/config/namespaces.ts Normal file
View File

@ -0,0 +1,2 @@
export const COMMON = 'common';
export const INDEX_PAGE = 'index-page';

View File

@ -1,7 +1,9 @@
import React from 'react';
import { useQueryParams, StringParam, withDefault } from 'use-query-params';
import { useDebouncedCallback } from 'use-debounce';
import { useTranslation } from 'react-i18next';
import { TWHELP } from '@config/app';
import * as NAMESPACES from '@config/namespaces';
import useStyles from './styles';
import {
@ -25,6 +27,7 @@ export default function Header() {
value => setQuery({ q: value }),
1000
);
const { t } = useTranslation(NAMESPACES.INDEX_PAGE);
const classes = useStyles();
return (
@ -35,7 +38,7 @@ export default function Header() {
<TextField
fullWidth
variant="outlined"
placeholder="Search"
placeholder={t<string>('header.search')}
defaultValue={query.q}
size="small"
onChange={e => {

View File

@ -6,10 +6,12 @@ import {
NumberParam,
withDefault,
} from 'use-query-params';
import { useTranslation } from 'react-i18next';
import formatDistanceToNow from '@libs/date/formatDistanceToNow';
import { Locale } from '@libs/date/locales';
import useLanguage from '@libs/i18n/useLanguage';
import { SERVER_STATUS } from '@config/app';
import * as NAMESPACES from '@config/namespaces';
import { ServerList } from './types';
import { SERVERS } from './queries';
import extractLangTagFromHostname from '@utils/extractLangTagFromHostname';
@ -28,6 +30,7 @@ export default function ServerSelection() {
page: withDefault(NumberParam, 1),
q: withDefault(StringParam, ''),
});
const { t } = useTranslation(NAMESPACES.INDEX_PAGE);
const lang = useLanguage();
const { data, loading: loadingServers } = useQuery<ServerList>(SERVERS, {
fetchPolicy: 'cache-and-network',
@ -97,18 +100,30 @@ export default function ServerSelection() {
<CardHeader
title={`${server.key}${
SERVER_STATUS.CLOSED === server.status
? ' (closed)'
? ` (${t(
NAMESPACES.COMMON +
`:serverStatus.${server.status}`
)})`.toLowerCase()
: ''
}`}
subheader={
<span>
{server.numberOfPlayers.toLocaleString()} players
{t('serverSelection.numberOfPlayers', {
count: server.numberOfPlayers,
num: server.numberOfPlayers.toLocaleString(),
})}
<br />
{server.numberOfTribes.toLocaleString()} tribes
{t('serverSelection.numberOfTribes', {
count: server.numberOfTribes,
num: server.numberOfTribes.toLocaleString(),
})}
<br />
{server.numberOfVillages.toLocaleString()} villages
{t('serverSelection.numberOfVillages', {
count: server.numberOfVillages,
num: server.numberOfVillages.toLocaleString(),
})}
<br />
Updated{' '}
{t('serverSelection.updated')}{' '}
{formatDistanceToNow(new Date(server.dataUpdatedAt), {
locale: lang as Locale,
addSuffix: true,

View File

@ -0,0 +1,18 @@
const translations = {
versionSelector: {
changeVersion: 'Change version',
},
pagination: {
page: 'Page',
first: 'Go to first page',
last: 'Go to last page',
next: 'Go to next page',
previous: 'Go to previous page',
},
serverStatus: {
closed: 'Closed',
open: 'Open',
},
};
export default translations;

View File

@ -0,0 +1,16 @@
const translations = {
header: {
search: 'Search',
},
serverSelection: {
numberOfPlayers: '{{num}} player',
numberOfPlayers_plural: '{{num}} players',
numberOfTribes: '{{num}} tribe',
numberOfTribes_plural: '{{num}} tribes',
numberOfVillages: '{{num}} village',
numberOfVillages_plural: '{{num}} villages',
updated: 'Updated',
},
};
export default translations;

View File

@ -1 +1,10 @@
export default {};
import * as NAMESPACES from '@config/namespaces';
import common from './common';
import indexPage from './index-page';
const translations = {
[NAMESPACES.COMMON]: common,
[NAMESPACES.INDEX_PAGE]: indexPage,
};
export default translations;

View File

@ -4,6 +4,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
import pl from './pl';
import en from './en';
import { DEFAULT_LANGUAGE } from '@config/app';
import { COMMON } from '@config/namespaces';
const init = (): i18nT => {
i18n
@ -20,7 +21,7 @@ const init = (): i18nT => {
en,
pl,
},
defaultNS: 'common',
defaultNS: COMMON,
react: {
useSuspense: false,
},

View File

@ -0,0 +1,18 @@
const translations = {
versionSelector: {
changeVersion: 'Zmień wersję',
},
pagination: {
page: 'Strona',
first: 'Przejdź do pierwszej strony',
last: 'Przejdź do ostatniej strony',
next: 'Przejdź do następnej strony',
previous: 'Przejdź do poprzedniej strony',
},
serverStatus: {
closed: 'Zamknięty',
open: 'Otwarty',
},
};
export default translations;

View File

@ -0,0 +1,19 @@
const translations = {
header: {
search: 'Szukaj',
},
serverSelection: {
numberOfPlayers_0: '{{num}} gracz',
numberOfPlayers_1: '{{num}} graczy',
numberOfPlayers_2: '{{num}} graczy',
numberOfTribes_0: '{{num}} plemię',
numberOfTribes_1: '{{num}} plemiona',
numberOfTribes_2: '{{num}} plemion',
numberOfVillages_0: '{{num}} wioska',
numberOfVillages_1: '{{num}} wioski',
numberOfVillages_2: '{{num}} wiosek',
updated: 'Zaktualizowany',
},
};
export default translations;

View File

@ -1 +1,10 @@
export default {};
import * as NAMESPACES from '@config/namespaces';
import common from './common';
import indexPage from './index-page';
const translations = {
[NAMESPACES.COMMON]: common,
[NAMESPACES.INDEX_PAGE]: indexPage,
};
export default translations;