mirror of
https://github.com/umami-software/umami.git
synced 2026-02-19 12:05:41 +01:00
i18n country names
This commit is contained in:
parent
e9f657492d
commit
adff1d7400
11 changed files with 47 additions and 83 deletions
|
|
@ -1,23 +1,19 @@
|
|||
import { useCallback } from 'react';
|
||||
import ListTable from 'components/metrics/ListTable';
|
||||
import { useLocale, useCountryNames, useMessages } from 'components/hooks';
|
||||
import { useMessages } from 'components/hooks';
|
||||
import { useIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import styles from './RealtimeCountries.module.css';
|
||||
import TypeIcon from 'components/common/TypeIcon';
|
||||
|
||||
export function RealtimeCountries({ data }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { locale } = useLocale();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const intl = useIntl();
|
||||
|
||||
const renderCountryName = useCallback(
|
||||
({ x: code }) => (
|
||||
<span className={classNames(locale, styles.row)}>
|
||||
<TypeIcon type="country" value={code?.toLowerCase()} />
|
||||
{countryNames[code]}
|
||||
</span>
|
||||
),
|
||||
[countryNames, locale],
|
||||
const renderCountryName = ({ x: code }) => (
|
||||
<span className={classNames(styles.row)}>
|
||||
<TypeIcon type="country" value={code?.toLowerCase()} />
|
||||
{intl.formatDisplayName(code, { type: 'region' })}
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import useFormat from 'components//hooks/useFormat';
|
||||
import Empty from 'components/common/Empty';
|
||||
import FilterButtons from 'components/common/FilterButtons';
|
||||
import { useCountryNames, useLocale, useMessages, useTimezone } from 'components/hooks';
|
||||
import { useMessages, useTimezone } from 'components/hooks';
|
||||
import Icons from 'components/icons';
|
||||
import { BROWSERS, OS_NAMES } from 'lib/constants';
|
||||
import { stringToColor } from 'lib/format';
|
||||
|
|
@ -31,9 +31,7 @@ export function RealtimeLog({ data }: { data: RealtimeData }) {
|
|||
const [search, setSearch] = useState('');
|
||||
const { formatMessage, labels, messages, FormattedMessage } = useMessages();
|
||||
const { formatValue } = useFormat();
|
||||
const { locale } = useLocale();
|
||||
const { formatTimezoneDate } = useTimezone();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const [filter, setFilter] = useState(TYPE_ALL);
|
||||
|
||||
const buttons = [
|
||||
|
|
@ -112,7 +110,12 @@ export function RealtimeLog({ data }: { data: RealtimeData }) {
|
|||
<FormattedMessage
|
||||
{...messages.visitorLog}
|
||||
values={{
|
||||
country: <b>{countryNames[country] || formatMessage(labels.unknown)}</b>,
|
||||
country: (
|
||||
<b>
|
||||
{intl.formatDisplayName(country, { type: 'region' }) ||
|
||||
formatMessage(labels.unknown)}
|
||||
</b>
|
||||
),
|
||||
browser: <b>{BROWSERS[browser]}</b>,
|
||||
os: <b>{OS_NAMES[os] || os}</b>,
|
||||
device: <b>{formatMessage(labels[device] || labels.unknown)}</b>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useFormat, useLocale, useMessages, useRegionNames, useTimezone } from 'components/hooks';
|
||||
import { useFormat, useMessages, useRegionNames, useTimezone } from 'components/hooks';
|
||||
import TypeIcon from 'components/common/TypeIcon';
|
||||
import { Icon, CopyIcon } from 'react-basics';
|
||||
import Icons from 'components/icons';
|
||||
|
|
@ -7,11 +7,10 @@ import { useIntl } from 'react-intl';
|
|||
|
||||
export default function SessionInfo({ data }) {
|
||||
const intl = useIntl();
|
||||
const { locale } = useLocale();
|
||||
const { formatTimezoneDate } = useTimezone();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { formatValue } = useFormat();
|
||||
const { getRegionName } = useRegionNames(locale);
|
||||
const { getRegionName } = useRegionNames();
|
||||
|
||||
return (
|
||||
<div className={styles.info}>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ export * from './queries/useWebsiteEvents';
|
|||
export * from './queries/useWebsiteEventsSeries';
|
||||
export * from './queries/useWebsiteMetrics';
|
||||
export * from './queries/useWebsiteValues';
|
||||
export * from './useCountryNames';
|
||||
export * from './useDateRange';
|
||||
export * from './useDocumentClick';
|
||||
export * from './useEscapeKey';
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { httpGet } from 'next-basics';
|
||||
import enUS from '../../../public/intl/country/en-US.json';
|
||||
|
||||
const countryNames = {
|
||||
'en-US': enUS,
|
||||
};
|
||||
|
||||
export function useCountryNames(locale: string) {
|
||||
const [list, setList] = useState(countryNames[locale] || enUS);
|
||||
|
||||
async function loadData(locale: string) {
|
||||
const { data } = await httpGet(`${process.env.basePath || ''}/intl/country/${locale}.json`);
|
||||
|
||||
if (data) {
|
||||
countryNames[locale] = data;
|
||||
setList(countryNames[locale]);
|
||||
} else {
|
||||
setList(enUS);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!countryNames[locale]) {
|
||||
loadData(locale);
|
||||
} else {
|
||||
setList(countryNames[locale]);
|
||||
}
|
||||
}, [locale]);
|
||||
|
||||
return { countryNames: list };
|
||||
}
|
||||
|
||||
export default useCountryNames;
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
import useMessages from './useMessages';
|
||||
import { BROWSERS, OS_NAMES } from 'lib/constants';
|
||||
import useLocale from './useLocale';
|
||||
import useCountryNames from './useCountryNames';
|
||||
import { useIntl } from 'react-intl';
|
||||
import regions from '../../../public/iso-3166-2.json';
|
||||
|
||||
export function useFormat() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { locale } = useLocale();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const intl = useIntl();
|
||||
|
||||
const formatOS = (value: string): string => {
|
||||
return OS_NAMES[value] || value;
|
||||
|
|
@ -22,16 +20,20 @@ export function useFormat() {
|
|||
};
|
||||
|
||||
const formatCountry = (value: string): string => {
|
||||
return countryNames[value] || value;
|
||||
return intl.formatDisplayName(value, { type: 'region' }) || value;
|
||||
};
|
||||
|
||||
const formatRegion = (value: string): string => {
|
||||
const [country] = value.split('-');
|
||||
return regions[value] ? `${regions[value]}, ${countryNames[country]}` : value;
|
||||
return regions[value]
|
||||
? `${regions[value]}, ${intl.formatDisplayName(country, { type: 'region' })}`
|
||||
: value;
|
||||
};
|
||||
|
||||
const formatCity = (value: string, country?: string): string => {
|
||||
return countryNames[country] ? `${value}, ${countryNames[country]}` : value;
|
||||
return intl.formatDisplayName(country, { type: 'region' })
|
||||
? `${value}, ${intl.formatDisplayName(country, { type: 'region' })}`
|
||||
: value;
|
||||
};
|
||||
|
||||
const formatValue = (value: string, type: string, data?: { [key: string]: any }): string => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import useCountryNames from './useCountryNames';
|
||||
import { useIntl } from 'react-intl';
|
||||
import regions from '../../../public/iso-3166-2.json';
|
||||
|
||||
export function useRegionNames(locale: string) {
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
export function useRegionNames() {
|
||||
const intl = useIntl();
|
||||
|
||||
const getRegionName = (regionCode: string, countryCode?: string) => {
|
||||
if (!countryCode) {
|
||||
|
|
@ -10,7 +10,9 @@ export function useRegionNames(locale: string) {
|
|||
}
|
||||
|
||||
const region = regionCode.includes('-') ? regionCode : `${countryCode}-${regionCode}`;
|
||||
return regions[region] ? `${regions[region]}, ${countryNames[countryCode]}` : region;
|
||||
return regions[region]
|
||||
? `${regions[region]}, ${intl.formatDisplayName(countryCode, { type: 'region' })}`
|
||||
: region;
|
||||
};
|
||||
|
||||
return { regionNames: regions, getRegionName };
|
||||
|
|
|
|||
|
|
@ -2,17 +2,15 @@ import MetricsTable, { MetricsTableProps } from './MetricsTable';
|
|||
import { emptyFilter } from 'lib/filters';
|
||||
import FilterLink from 'components/common/FilterLink';
|
||||
import TypeIcon from 'components/common/TypeIcon';
|
||||
import { useLocale } from 'components/hooks';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMessages } from 'components/hooks';
|
||||
import { useCountryNames } from 'components/hooks';
|
||||
|
||||
export function CitiesTable(props: MetricsTableProps) {
|
||||
const { locale } = useLocale();
|
||||
const intl = useIntl();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
|
||||
const renderLabel = (city: string, country: string) => {
|
||||
const countryName = countryNames[country];
|
||||
const countryName = intl.formatDisplayName(country, { type: 'region' });
|
||||
return countryName ? `${city}, ${countryName}` : city;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import FilterLink from 'components/common/FilterLink';
|
||||
import { useCountryNames } from 'components/hooks';
|
||||
import { useLocale, useMessages, useFormat } from 'components/hooks';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMessages, useFormat } from 'components/hooks';
|
||||
import MetricsTable, { MetricsTableProps } from './MetricsTable';
|
||||
import TypeIcon from 'components/common/TypeIcon';
|
||||
|
||||
export function CountriesTable({ ...props }: MetricsTableProps) {
|
||||
const { locale } = useLocale();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const intl = useIntl();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { formatCountry } = useFormat();
|
||||
|
||||
|
|
@ -14,8 +13,7 @@ export function CountriesTable({ ...props }: MetricsTableProps) {
|
|||
return (
|
||||
<FilterLink
|
||||
id="country"
|
||||
className={locale}
|
||||
value={countryNames[code] && code}
|
||||
value={intl.formatDisplayName(code, { type: 'region' }) && code}
|
||||
label={formatCountry(code)}
|
||||
>
|
||||
<TypeIcon type="country" value={code?.toLowerCase()} />
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
import FilterLink from 'components/common/FilterLink';
|
||||
import { emptyFilter } from 'lib/filters';
|
||||
import { useMessages, useLocale, useRegionNames } from 'components/hooks';
|
||||
import { useMessages, useRegionNames } from 'components/hooks';
|
||||
import MetricsTable, { MetricsTableProps } from './MetricsTable';
|
||||
import TypeIcon from 'components/common/TypeIcon';
|
||||
|
||||
export function RegionsTable(props: MetricsTableProps) {
|
||||
const { locale } = useLocale();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { getRegionName } = useRegionNames(locale);
|
||||
const { getRegionName } = useRegionNames();
|
||||
|
||||
const renderLink = ({ x: code, country }) => {
|
||||
return (
|
||||
<FilterLink id="region" className={locale} value={code} label={getRegionName(code, country)}>
|
||||
<FilterLink id="region" value={code} label={getRegionName(code, country)}>
|
||||
<TypeIcon type="country" value={country?.toLowerCase()} />
|
||||
</FilterLink>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { colord } from 'colord';
|
|||
import HoverTooltip from 'components/common/HoverTooltip';
|
||||
import { ISO_COUNTRIES, MAP_FILE } from 'lib/constants';
|
||||
import { useDateRange, useTheme, useWebsiteMetrics } from 'components/hooks';
|
||||
import { useCountryNames } from 'components/hooks';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useLocale } from 'components/hooks';
|
||||
import { useMessages } from 'components/hooks';
|
||||
import { formatLongNumber } from 'lib/format';
|
||||
|
|
@ -26,7 +26,7 @@ export function WorldMap({
|
|||
const { theme, colors } = useTheme();
|
||||
const { locale } = useLocale();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const intl = useIntl();
|
||||
const visitorsLabel = formatMessage(labels.visitors).toLocaleLowerCase(locale);
|
||||
const {
|
||||
dateRange: { startDate, endDate },
|
||||
|
|
@ -62,7 +62,9 @@ export function WorldMap({
|
|||
if (code === 'AQ') return;
|
||||
const country = metrics?.find(({ x }) => x === code);
|
||||
setTooltipPopup(
|
||||
`${countryNames[code]}: ${formatLongNumber(country?.y || 0)} ${visitorsLabel}` as any,
|
||||
`${intl.formatDisplayName(code, { type: 'region' })}: ${formatLongNumber(
|
||||
country?.y || 0,
|
||||
)} ${visitorsLabel}` as any,
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue