mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-12 20:47:38 +01:00
commit
a2fdab6c9b
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,6 +17,7 @@
|
||||
/build
|
||||
/public/umami.js
|
||||
/public/geo
|
||||
/public/lang
|
||||
/lang-compiled
|
||||
|
||||
# misc
|
||||
|
@ -10,7 +10,7 @@ A detailed getting started guide can be found at [https://umami.is/docs/](https:
|
||||
|
||||
### Requirements
|
||||
|
||||
- A server with Node.js 10.13 or newer
|
||||
- A server with Node.js 12 or newer
|
||||
- A database (MySQL or Postgresql)
|
||||
|
||||
### Get the source code and install packages
|
||||
|
@ -27,7 +27,7 @@ import styles from './Calendar.module.css';
|
||||
import Icon from './Icon';
|
||||
|
||||
export default function Calendar({ date, minDate, maxDate, onChange }) {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const [selectMonth, setSelectMonth] = useState(false);
|
||||
const [selectYear, setSelectYear] = useState(false);
|
||||
|
||||
|
@ -55,7 +55,7 @@ const filterOptions = [
|
||||
];
|
||||
|
||||
function DateFilter({ value, startDate, endDate, onChange, className }) {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
const displayValue =
|
||||
value === 'custom' ? (
|
||||
@ -102,7 +102,7 @@ function DateFilter({ value, startDate, endDate, onChange, className }) {
|
||||
}
|
||||
|
||||
const CustomRange = ({ startDate, endDate, onClick }) => {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
|
||||
function handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -12,7 +12,7 @@ import useLocale from 'hooks/useLocale';
|
||||
|
||||
function RefreshButton({ websiteId }) {
|
||||
const dispatch = useDispatch();
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const [dateRange] = useDateRange(websiteId);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const completed = useSelector(state => state.queries[`/api/website/${websiteId}/stats`]);
|
||||
|
@ -24,7 +24,7 @@ function WorldMap({ data, className }) {
|
||||
}),
|
||||
[theme],
|
||||
);
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const countryNames = useCountryNames(locale);
|
||||
|
||||
function getFillColor(code) {
|
||||
|
@ -9,7 +9,7 @@ import { rtlLocales } from 'lib/lang';
|
||||
|
||||
export default function Footer() {
|
||||
const { current } = useVersion();
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
|
||||
return (
|
||||
<footer className="container" dir={rtlLocales.includes(locale) ? 'rtl' : 'ltr'}>
|
||||
|
@ -19,7 +19,7 @@ import Bars from 'assets/bars.svg';
|
||||
export default function Header() {
|
||||
const user = useSelector(state => state.user);
|
||||
const [active, setActive] = useState(false);
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
|
||||
function handleClick() {
|
||||
setActive(state => !state);
|
||||
|
@ -6,7 +6,7 @@ import useLocale from 'hooks/useLocale';
|
||||
import { rtlLocales } from 'lib/lang';
|
||||
|
||||
export default function Layout({ title, children, header = true, footer = true }) {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const dir = rtlLocales.includes(locale) ? 'rtl' : 'ltr';
|
||||
|
||||
return (
|
||||
|
@ -27,7 +27,7 @@ export default function BarChart({
|
||||
const canvas = useRef();
|
||||
const chart = useRef();
|
||||
const [tooltip, setTooltip] = useState(null);
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const [theme] = useTheme();
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
|
@ -6,7 +6,7 @@ import useCountryNames from 'hooks/useCountryNames';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
|
||||
export default function CountriesTable({ websiteId, onDataLoad, ...props }) {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const countryNames = useCountryNames(locale);
|
||||
|
||||
function renderLabel({ x }) {
|
||||
|
@ -6,7 +6,7 @@ import styles from './Legend.module.css';
|
||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||
|
||||
export default function Legend({ chart }) {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
function handleClick(index) {
|
||||
|
@ -31,7 +31,7 @@ const TYPE_ICONS = {
|
||||
|
||||
export default function RealtimeLog({ data, websites, websiteId }) {
|
||||
const intl = useIntl();
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const countryNames = useCountryNames(locale);
|
||||
const [filter, setFilter] = useState(TYPE_ALL);
|
||||
|
||||
|
@ -29,7 +29,7 @@ function filterWebsite(data, id) {
|
||||
}
|
||||
|
||||
export default function RealtimeDashboard() {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const countryNames = useCountryNames(locale);
|
||||
const [data, setData] = useState();
|
||||
const [websiteId, setWebsiteId] = useState(0);
|
||||
|
@ -9,7 +9,7 @@ import styles from './DateRangeSetting.module.css';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
|
||||
export default function DateRangeSetting() {
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const [dateRange, setDateRange] = useDateRange();
|
||||
const { startDate, endDate, value } = dateRange;
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
import React from 'react';
|
||||
import { menuOptions } from 'lib/lang';
|
||||
import { languages } from 'lib/lang';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import MenuButton from 'components/common/MenuButton';
|
||||
import Globe from 'assets/globe.svg';
|
||||
import styles from './LanguageButton.module.css';
|
||||
|
||||
export default function LanguageButton() {
|
||||
const [locale, setLocale] = useLocale();
|
||||
const { locale, saveLocale } = useLocale();
|
||||
const menuOptions = Object.keys(languages).map(key => ({ ...languages[key], value: key }));
|
||||
|
||||
function handleSelect(value) {
|
||||
setLocale(value);
|
||||
saveLocale(value);
|
||||
}
|
||||
|
||||
switch (locale) {
|
||||
|
@ -11,6 +11,7 @@ services:
|
||||
HASH_SALT: replace-me-with-a-random-string
|
||||
depends_on:
|
||||
- db
|
||||
restart: always
|
||||
db:
|
||||
image: postgres:12-alpine
|
||||
environment:
|
||||
@ -20,5 +21,6 @@ services:
|
||||
volumes:
|
||||
- ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro
|
||||
- umami-db-data:/var/lib/postgresql/data
|
||||
restart: always
|
||||
volumes:
|
||||
umami-db-data:
|
||||
|
@ -9,7 +9,7 @@ import useLocale from './useLocale';
|
||||
|
||||
export default function useDateRange(websiteId, defaultDateRange = DEFAULT_DATE_RANGE) {
|
||||
const dispatch = useDispatch();
|
||||
const [locale] = useLocale();
|
||||
const { locale } = useLocale();
|
||||
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
|
@ -1,16 +1,49 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { setLocale } from 'redux/actions/app';
|
||||
import { setItem } from 'lib/web';
|
||||
import { useRouter } from 'next/router';
|
||||
import { get, setItem } from 'lib/web';
|
||||
import { LOCALE_CONFIG } from 'lib/constants';
|
||||
import useForceUpdate from 'hooks/useForceUpdate';
|
||||
import enUS from 'public/lang/en-US.json';
|
||||
|
||||
const messages = {
|
||||
'en-US': enUS,
|
||||
};
|
||||
|
||||
export default function useLocale() {
|
||||
const locale = useSelector(state => state.app.locale);
|
||||
const dispatch = useDispatch();
|
||||
const { basePath } = useRouter();
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
function saveLocale(value) {
|
||||
setItem(LOCALE_CONFIG, value);
|
||||
dispatch(setLocale(value));
|
||||
async function loadMessages(locale) {
|
||||
const { ok, data } = await get(`${basePath}/lang/${locale}.json`);
|
||||
|
||||
if (ok) {
|
||||
messages[locale] = data;
|
||||
}
|
||||
}
|
||||
|
||||
return [locale, saveLocale];
|
||||
async function saveLocale(value) {
|
||||
if (!messages[value]) {
|
||||
await loadMessages(value);
|
||||
}
|
||||
|
||||
setItem(LOCALE_CONFIG, value);
|
||||
|
||||
if (locale !== value) {
|
||||
dispatch(setLocale(value));
|
||||
} else {
|
||||
forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!messages[locale]) {
|
||||
saveLocale(locale);
|
||||
}
|
||||
}, [locale]);
|
||||
|
||||
return { locale, saveLocale, messages };
|
||||
}
|
||||
|
100
lang/hu-HU.json
Normal file
100
lang/hu-HU.json
Normal file
@ -0,0 +1,100 @@
|
||||
{
|
||||
"label.accounts": "Fiókok",
|
||||
"label.add-account": "Fiók hozzáadása",
|
||||
"label.add-website": "Weboldal hozzáadása",
|
||||
"label.administrator": "Adminisztrátor",
|
||||
"label.all": "Összes",
|
||||
"label.all-websites": "Összes weboldal",
|
||||
"label.all-events": "Összes esemény",
|
||||
"label.back": "Vissza",
|
||||
"label.cancel": "Mégsem",
|
||||
"label.change-password": "Jelszó módosítása",
|
||||
"label.confirm-password": "Jelszó megerősítése",
|
||||
"label.copy-to-clipboard": "Vágólapra másolás",
|
||||
"label.current-password": "Jelenlegi jelszó",
|
||||
"label.custom-range": "Egyedi tartomány",
|
||||
"label.dashboard": "Áttekintés",
|
||||
"label.date-range": "Időintervallum",
|
||||
"label.default-date-range": "Alapértelmezett időintervallum",
|
||||
"label.delete": "Eltávolítás",
|
||||
"label.delete-account": "Fiók eltávolítása",
|
||||
"label.delete-website": "Weboldal eltávolítása",
|
||||
"label.dismiss": "Mellőzés",
|
||||
"label.domain": "Domain",
|
||||
"label.edit": "Módosítás",
|
||||
"label.edit-account": "Fiók módosítása",
|
||||
"label.edit-website": "Weboldal módosítása",
|
||||
"label.enable-share-url": "URL-megosztás engedélyezése",
|
||||
"label.invalid": "Érvénytelen",
|
||||
"label.invalid-domain": "Érvénytelen domain",
|
||||
"label.last-days": "Legutóbbi {x} nap",
|
||||
"label.last-hours": "Legutóbbi {x} óra",
|
||||
"label.logged-in-as": "Bejelentkezve, mint {username}",
|
||||
"label.login": "Bejelentkezés",
|
||||
"label.logout": "Kijelentkezés",
|
||||
"label.more": "Bővebben",
|
||||
"label.name": "Név",
|
||||
"label.new-password": "Új jelszó",
|
||||
"label.password": "Jelszó",
|
||||
"label.passwords-dont-match": "A jelszavak nem egyeznek",
|
||||
"label.profile": "Profil",
|
||||
"label.realtime": "Valós idejű",
|
||||
"label.realtime-logs": "Valós idejű napló",
|
||||
"label.refresh": "Frissítés",
|
||||
"label.required": "Kötelező",
|
||||
"label.reset": "Visszaállítás",
|
||||
"label.save": "Mentés",
|
||||
"label.settings": "Beállítások",
|
||||
"label.share-url": "URL megosztása",
|
||||
"label.single-day": "Egy nap",
|
||||
"label.this-month": "Ezen hónap",
|
||||
"label.this-week": "Ezen hét",
|
||||
"label.this-year": "Ezen év",
|
||||
"label.timezone": "Időzóna",
|
||||
"label.today": "Ma",
|
||||
"label.tracking-code": "Követési kód",
|
||||
"label.unknown": "Ismeretlen",
|
||||
"label.username": "Felhasználónév",
|
||||
"label.view-details": "Részletek",
|
||||
"label.websites": "Weboldalak",
|
||||
"message.active-users": "{x} {x, plural, one {látogató} other {latógató}} jelenleg",
|
||||
"message.confirm-delete": "Biztos, hogy törölni szeretnéd {target} elemet?",
|
||||
"message.copied": "Kimásolva!",
|
||||
"message.delete-warning": "Minden társított adat törlésre kerül.",
|
||||
"message.failure": "Valami baj történt.",
|
||||
"message.get-share-url": "Megosztási URL kimásolása",
|
||||
"message.get-tracking-code": "Követési kód kimásolása",
|
||||
"message.go-to-settings": "Tovább a beállításokhoz",
|
||||
"message.incorrect-username-password": "Érvénytelen felhasználónév/jelszó.",
|
||||
"message.log.visitor": "Látógató {country} területéről, {os} {device} eszközön, {browser} böngészőből.",
|
||||
"message.new-version-available": "Elérhető az umami {version} új verziója!",
|
||||
"message.no-data-available": "Nincs rendelkezésre álló adat.",
|
||||
"message.no-websites-configured": "Még nem állítottál be egyetlen weboldalt sem.",
|
||||
"message.page-not-found": "Oldal nem található.",
|
||||
"message.powered-by": "Működteti az {name}",
|
||||
"message.save-success": "Sikeres mentés.",
|
||||
"message.share-url": "{target} nyilvánosan megosztott URL címe.",
|
||||
"message.track-stats": "{target} statisztikáinak nyomon követéséhez, helyezd el az alábbi kódot a weboldalad {head} részébe.",
|
||||
"message.type-delete": "Megerősítéshez írd be az alábbi mezőbe azt, hogy {delete}.",
|
||||
"metrics.actions": "Műveletek",
|
||||
"metrics.average-visit-time": "Átlagos látogatási idő",
|
||||
"metrics.bounce-rate": "Visszafordulási arány",
|
||||
"metrics.browsers": "Böngészők",
|
||||
"metrics.countries": "Országok",
|
||||
"metrics.device.desktop": "Asztali számítógép",
|
||||
"metrics.device.laptop": "Laptop",
|
||||
"metrics.device.mobile": "Telefon",
|
||||
"metrics.device.tablet": "Táblagép",
|
||||
"metrics.devices": "Eszközök",
|
||||
"metrics.events": "Események",
|
||||
"metrics.filter.combined": "Összevont",
|
||||
"metrics.filter.domain-only": "Csak domain",
|
||||
"metrics.filter.raw": "Nyers",
|
||||
"metrics.operating-systems": "Operációs rendszerek",
|
||||
"metrics.page-views": "Oldalmegtekintések",
|
||||
"metrics.pages": "Oldalak",
|
||||
"metrics.referrers": "Hivatkozók",
|
||||
"metrics.unique-visitors": "Egyedi látogatók",
|
||||
"metrics.views": "Megtekintések",
|
||||
"metrics.visitors": "Látogatók"
|
||||
}
|
@ -57,29 +57,29 @@
|
||||
"label.view-details": "查看更多",
|
||||
"label.websites": "網站",
|
||||
"message.active-users": "当前線上 {x} 人",
|
||||
"message.confirm-delete": "你確定要删除{target}嗎?",
|
||||
"message.copied": "複製成功!",
|
||||
"message.delete-warning": "所有相關數據將會被删除.",
|
||||
"message.failure": "出現錯誤.",
|
||||
"message.confirm-delete": "你確定要删除 {target} 嗎?",
|
||||
"message.copied": "複製成功!",
|
||||
"message.delete-warning": "所有相關數據將會被删除。",
|
||||
"message.failure": "出現錯誤。",
|
||||
"message.get-share-url": "獲得分享連結",
|
||||
"message.get-tracking-code": "獲得追蹤代碼",
|
||||
"message.go-to-settings": "去設定",
|
||||
"message.incorrect-username-password": "用户名或密碼不正確.",
|
||||
"message.log.visitor": "自 {country} 的訪客在搭載 {os} 的 {device} 上使用 {browser} 進行訪問.",
|
||||
"message.incorrect-username-password": "用户名或密碼不正確。",
|
||||
"message.log.visitor": "自 {country} 的訪客在搭載 {os} 的 {device} 上使用 {browser} 進行訪問。",
|
||||
"message.new-version-available": "umami 有新版本 {version} 發佈啦!",
|
||||
"message.no-data-available": "無可用數據.",
|
||||
"message.no-websites-configured": "目前無任何網站設定.",
|
||||
"message.page-not-found": "網頁未找到.",
|
||||
"message.no-data-available": "無可用數據。",
|
||||
"message.no-websites-configured": "目前無任何網站設定。",
|
||||
"message.page-not-found": "網頁未找到。",
|
||||
"message.powered-by": "運行 {name}",
|
||||
"message.save-success": "成功保存.",
|
||||
"message.share-url": "這是 {target} 的分享連結.",
|
||||
"message.track-stats": "將以下代碼放入被設定網站的{head}部分来收集{target}的資料.",
|
||||
"message.type-delete": "在下方空格輸入{delete}確認",
|
||||
"message.save-success": "成功保存。",
|
||||
"message.share-url": "這是 {target} 的分享連結。",
|
||||
"message.track-stats": "將以下代碼放入被設定網站的 {head} 部分来收集 {target} 的資料。",
|
||||
"message.type-delete": "在下方空格輸入 {delete} 確認",
|
||||
"metrics.actions": "用戶行為",
|
||||
"metrics.average-visit-time": "平均訪問時間",
|
||||
"metrics.bounce-rate": "跳出率",
|
||||
"metrics.browsers": "瀏覽器",
|
||||
"metrics.countries": "國家",
|
||||
"metrics.countries": "國家/地區",
|
||||
"metrics.device.desktop": "桌機",
|
||||
"metrics.device.laptop": "筆記本",
|
||||
"metrics.device.mobile": "手機",
|
||||
@ -94,6 +94,6 @@
|
||||
"metrics.pages": "網頁",
|
||||
"metrics.referrers": "指入域名",
|
||||
"metrics.unique-visitors": "獨立訪客",
|
||||
"metrics.views": "页面流量",
|
||||
"metrics.views": "頁面流量",
|
||||
"metrics.visitors": "獨立訪客"
|
||||
}
|
140
lib/lang.js
140
lib/lang.js
@ -31,75 +31,44 @@ import {
|
||||
zhCN,
|
||||
zhTW,
|
||||
ca,
|
||||
hu,
|
||||
} from 'date-fns/locale';
|
||||
import arSAMessages from 'lang-compiled/ar-SA.json';
|
||||
import enMessages from 'lang-compiled/en-US.json';
|
||||
import nlMessages from 'lang-compiled/nl-NL.json';
|
||||
import zhCNMessages from 'lang-compiled/zh-CN.json';
|
||||
import zhTWMessages from 'lang-compiled/zh-TW.json';
|
||||
import trTRMessages from 'lang-compiled/tr-TR.json';
|
||||
import ruRUMessages from 'lang-compiled/ru-RU.json';
|
||||
import deDEMessages from 'lang-compiled/de-DE.json';
|
||||
import jaMessages from 'lang-compiled/ja-JP.json';
|
||||
import esMXMessages from 'lang-compiled/es-MX.json';
|
||||
import frMessages from 'lang-compiled/fr-FR.json';
|
||||
import mnMNMessages from 'lang-compiled/mn-MN.json';
|
||||
import daMessages from 'lang-compiled/da-DK.json';
|
||||
import svMessages from 'lang-compiled/sv-SE.json';
|
||||
import grMessages from 'lang-compiled/el-GR.json';
|
||||
import foMessages from 'lang-compiled/fo-FO.json';
|
||||
import ptMessages from 'lang-compiled/pt-PT.json';
|
||||
import ptBRMessages from 'lang-compiled/pt-BR.json';
|
||||
import roMessages from 'lang-compiled/ro-RO.json';
|
||||
import nbNOMessages from 'lang-compiled/nb-NO.json';
|
||||
import idMessages from 'lang-compiled/id-ID.json';
|
||||
import ukMessages from 'lang-compiled/uk-UA.json';
|
||||
import fiMessages from 'lang-compiled/fi-FI.json';
|
||||
import csMessages from 'lang-compiled/cs-CZ.json';
|
||||
import skMessages from 'lang-compiled/sk-SK.json';
|
||||
import plMessages from 'lang-compiled/pl-PL.json';
|
||||
import taMessages from 'lang-compiled/ta-IN.json';
|
||||
import hiMessages from 'lang-compiled/hi-IN.json';
|
||||
import heMessages from 'lang-compiled/he-IL.json';
|
||||
import itMessages from 'lang-compiled/it-IT.json';
|
||||
import faIRMessages from 'lang-compiled/fa-IR.json';
|
||||
import msMYMessages from 'lang-compiled/ms-MY.json';
|
||||
import caMessages from 'lang-compiled/ca-ES.json';
|
||||
|
||||
export const messages = {
|
||||
'ar-SA': arSAMessages,
|
||||
'en-US': enMessages,
|
||||
'nl-NL': nlMessages,
|
||||
'zh-CN': zhCNMessages,
|
||||
'zh-TW': zhTWMessages,
|
||||
'de-DE': deDEMessages,
|
||||
'ru-RU': ruRUMessages,
|
||||
'tr-TR': trTRMessages,
|
||||
'ja-JP': jaMessages,
|
||||
'es-MX': esMXMessages,
|
||||
'fr-FR': frMessages,
|
||||
'mn-MN': mnMNMessages,
|
||||
'da-DK': daMessages,
|
||||
'sv-SE': svMessages,
|
||||
'el-GR': grMessages,
|
||||
'fo-FO': foMessages,
|
||||
'pt-PT': ptMessages,
|
||||
'pt-BR': ptBRMessages,
|
||||
'ro-RO': roMessages,
|
||||
'nb-NO': nbNOMessages,
|
||||
'id-ID': idMessages,
|
||||
'uk-UA': ukMessages,
|
||||
'fi-FI': fiMessages,
|
||||
'cs-CZ': csMessages,
|
||||
'sk-SK': skMessages,
|
||||
'pl-PL': plMessages,
|
||||
'ta-IN': taMessages,
|
||||
'hi-IN': hiMessages,
|
||||
'he-IL': heMessages,
|
||||
'it-IT': itMessages,
|
||||
'fa-IR': faIRMessages,
|
||||
'ms-MY': msMYMessages,
|
||||
'ca-ES': caMessages,
|
||||
export const languages = {
|
||||
'ar-SA': { label: 'العربية', display: 'ar' },
|
||||
'zh-CN': { label: '中文', display: 'cn' },
|
||||
'zh-TW': { label: '中文(繁體)', display: 'tw' },
|
||||
'ca-ES': { label: 'Català', display: 'ca' },
|
||||
'cs-CZ': { label: 'Čeština', display: 'cs' },
|
||||
'da-DK': { label: 'Dansk', display: 'da' },
|
||||
'de-DE': { label: 'Deutsch', display: 'de' },
|
||||
'en-US': { label: 'English', display: 'en' },
|
||||
'es-MX': { label: 'Español', display: 'es' },
|
||||
'fa-IR': { label: 'فارسی', display: 'fa' },
|
||||
'fo-FO': { label: 'Føroyskt', display: 'fo' },
|
||||
'fr-FR': { label: 'Français', display: 'fr' },
|
||||
'el-GR': { label: 'Ελληνικά', display: 'el' },
|
||||
'he-IL': { label: 'עברית', display: 'he' },
|
||||
'hi-IN': { label: 'हिन्दी', display: 'hi' },
|
||||
'hu-HU': { label: 'Hungarian', display: 'hu' },
|
||||
'it-IT': { label: 'Italiano', display: 'it' },
|
||||
'id-ID': { label: 'Bahasa Indonesia', display: 'id' },
|
||||
'ja-JP': { label: '日本語', display: 'ja' },
|
||||
'ms-MY': { label: 'Malay', display: 'ms' },
|
||||
'mn-MN': { label: 'Монгол', display: 'mn' },
|
||||
'nl-NL': { label: 'Nederlands', display: 'nl' },
|
||||
'nb-NO': { label: 'Norsk Bokmål', display: 'nb' },
|
||||
'pl-PL': { label: 'Polski', display: 'pl' },
|
||||
'pt-PT': { label: 'Português', display: 'pt' },
|
||||
'pt-BR': { label: 'Português do Brasil', display: 'pt-BR' },
|
||||
'ru-RU': { label: 'Русский', display: 'ru' },
|
||||
'ro-RO': { label: 'Română', display: 'ro' },
|
||||
'sk-SK': { label: 'Slovenčina', display: 'sk' },
|
||||
'fi-FI': { label: 'Suomi', display: 'fi' },
|
||||
'sv-SE': { label: 'Svenska', display: 'sv' },
|
||||
'ta-IN': { label: 'தமிழ்', display: 'ta' },
|
||||
'tr-TR': { label: 'Türkçe', display: 'tr' },
|
||||
'uk-UA': { label: 'українська', display: 'uk' },
|
||||
};
|
||||
|
||||
export const rtlLocales = ['ar-SA', 'fa-IR'];
|
||||
@ -138,40 +107,5 @@ export const dateLocales = {
|
||||
'fa-IR': faIR,
|
||||
'ms-MY': ms,
|
||||
'ca-ES': ca,
|
||||
'hu-HU': hu,
|
||||
};
|
||||
|
||||
export const menuOptions = [
|
||||
{ label: 'العربية', value: 'ar-SA', display: 'ar' },
|
||||
{ label: '中文', value: 'zh-CN', display: 'cn' },
|
||||
{ label: '中文(繁體)', value: 'zh-TW', display: 'tw' },
|
||||
{ label: 'Català', value: 'ca-ES', display: 'ca' },
|
||||
{ label: 'Čeština', value: 'cs-CZ', display: 'cs' },
|
||||
{ label: 'Dansk', value: 'da-DK', display: 'da' },
|
||||
{ label: 'Deutsch', value: 'de-DE', display: 'de' },
|
||||
{ label: 'English', value: 'en-US', display: 'en' },
|
||||
{ label: 'Español', value: 'es-MX', display: 'es' },
|
||||
{ label: 'فارسی', value: 'fa-IR', display: 'fa' },
|
||||
{ label: 'Føroyskt', value: 'fo-FO', display: 'fo' },
|
||||
{ label: 'Français', value: 'fr-FR', display: 'fr' },
|
||||
{ label: 'Ελληνικά', value: 'el-GR', display: 'el' },
|
||||
{ label: 'עברית', value: 'he-IL', display: 'he' },
|
||||
{ label: 'हिन्दी', value: 'hi-IN', display: 'hi' },
|
||||
{ label: 'Italiano', value: 'it-IT', display: 'it' },
|
||||
{ label: 'Bahasa Indonesia', value: 'id-ID', display: 'id' },
|
||||
{ label: '日本語', value: 'ja-JP', display: 'ja' },
|
||||
{ label: 'Malay', value: 'ms-MY', display: 'ms' },
|
||||
{ label: 'Монгол', value: 'mn-MN', display: 'mn' },
|
||||
{ label: 'Nederlands', value: 'nl-NL', display: 'nl' },
|
||||
{ label: 'Norsk Bokmål', value: 'nb-NO', display: 'nb' },
|
||||
{ label: 'Polski', value: 'pl-PL', display: 'pl' },
|
||||
{ label: 'Português', value: 'pt-PT', display: 'pt' },
|
||||
{ label: 'Português do Brasil', value: 'pt-BR', display: 'pt-BR' },
|
||||
{ label: 'Русский', value: 'ru-RU', display: 'ru' },
|
||||
{ label: 'Română', value: 'ro-RO', display: 'ro' },
|
||||
{ label: 'Slovenčina', value: 'sk-SK', display: 'sk' },
|
||||
{ label: 'Suomi', value: 'fi-FI', display: 'fi' },
|
||||
{ label: 'Svenska', value: 'sv-SE', display: 'sv' },
|
||||
{ label: 'தமிழ்', value: 'ta-IN', display: 'ta' },
|
||||
{ label: 'Türkçe', value: 'tr-TR', display: 'tr' },
|
||||
{ label: 'українська', value: 'uk-UA', display: 'uk' },
|
||||
];
|
||||
|
@ -10,9 +10,7 @@ module.exports = {
|
||||
webpack(config) {
|
||||
config.module.rules.push({
|
||||
test: /\.svg$/,
|
||||
issuer: {
|
||||
test: /\.js$/,
|
||||
},
|
||||
issuer: /\.js$/,
|
||||
use: ['@svgr/webpack'],
|
||||
});
|
||||
|
||||
|
45
package.json
45
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "umami",
|
||||
"version": "1.18.0",
|
||||
"version": "1.19.0",
|
||||
"description": "A simple, fast, website analytics alternative to Google Analytics. ",
|
||||
"author": "Mike Cao <mike@mikecao.com>",
|
||||
"license": "MIT",
|
||||
@ -30,7 +30,7 @@
|
||||
"extract-lang": "formatjs extract '{pages,components}/**/*.js' --out-file build/messages.json",
|
||||
"merge-lang": "node scripts/merge-lang.js",
|
||||
"format-lang": "node scripts/format-lang.js",
|
||||
"compile-lang": "formatjs compile-folder --ast build lang-compiled",
|
||||
"compile-lang": "formatjs compile-folder --ast build public/lang",
|
||||
"check-lang": "node scripts/check-lang.js",
|
||||
"download-country-names": "node scripts/download-country-names.js",
|
||||
"loadtest": "node scripts/loadtest.js",
|
||||
@ -56,11 +56,11 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^4.3.0",
|
||||
"@fontsource/noto-sans-jp": "^4.3.0",
|
||||
"@fontsource/noto-sans-sc": "^4.3.0",
|
||||
"@fontsource/noto-sans-tc": "^4.3.0",
|
||||
"@prisma/client": "2.23.0",
|
||||
"@fontsource/inter": "^4.5.0",
|
||||
"@fontsource/noto-sans-jp": "^4.5.0",
|
||||
"@fontsource/noto-sans-sc": "^4.5.0",
|
||||
"@fontsource/noto-sans-tc": "^4.5.0",
|
||||
"@prisma/client": "2.26.0",
|
||||
"@reduxjs/toolkit": "^1.5.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"chalk": "^4.1.1",
|
||||
@ -68,28 +68,28 @@
|
||||
"classnames": "^2.3.1",
|
||||
"cookie": "^0.4.1",
|
||||
"cors": "^2.8.5",
|
||||
"date-fns": "^2.21.3",
|
||||
"date-fns-tz": "^1.0.12",
|
||||
"date-fns": "^2.22.1",
|
||||
"date-fns-tz": "^1.1.4",
|
||||
"detect-browser": "^5.2.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"formik": "^2.2.7",
|
||||
"immer": "^9.0.2",
|
||||
"ipaddr.js": "^2.0.0",
|
||||
"formik": "^2.2.9",
|
||||
"immer": "^9.0.5",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"is-localhost-ip": "^1.4.0",
|
||||
"isbot": "^3.0.26",
|
||||
"isbot": "^3.1.0",
|
||||
"jose": "2.0.5",
|
||||
"maxmind": "^4.3.1",
|
||||
"maxmind": "^4.3.2",
|
||||
"moment-timezone": "^0.5.33",
|
||||
"next": "^10.2.2",
|
||||
"next": "^11.0.1",
|
||||
"prompts": "2.4.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-intl": "^5.16.0",
|
||||
"react-intl": "^5.20.4",
|
||||
"react-redux": "^7.2.4",
|
||||
"react-simple-maps": "^2.3.0",
|
||||
"react-spring": "^8.0.27",
|
||||
"react-tooltip": "^4.2.19",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"react-use-measure": "^2.0.4",
|
||||
"react-window": "^1.8.6",
|
||||
"redux": "^4.1.0",
|
||||
@ -102,7 +102,7 @@
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/cli": "^4.2.15",
|
||||
"@formatjs/cli": "^4.2.27",
|
||||
"@rollup/plugin-buble": "^0.21.3",
|
||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
@ -110,10 +110,11 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"del": "^6.0.0",
|
||||
"dotenv-cli": "^4.0.0",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint": "^7.30.0",
|
||||
"eslint-config-next": "^11.0.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"extract-react-intl-messages": "^4.1.1",
|
||||
"husky": "^4.3.8",
|
||||
@ -125,9 +126,9 @@
|
||||
"postcss-import": "^13.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"postcss-rtlcss": "^3.3.2",
|
||||
"prettier": "^2.3.0",
|
||||
"prettier": "^2.3.2",
|
||||
"prettier-eslint": "^12.0.0",
|
||||
"prisma": "2.23.0",
|
||||
"prisma": "2.26.0",
|
||||
"rollup": "^2.48.0",
|
||||
"rollup-plugin-hashbang": "^2.2.2",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
|
@ -6,7 +6,6 @@ import { Provider } from 'react-redux';
|
||||
import { useStore } from 'redux/store';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import useForceSSL from 'hooks/useForceSSL';
|
||||
import { messages } from 'lib/lang';
|
||||
import 'styles/variables.css';
|
||||
import 'styles/bootstrap-grid.css';
|
||||
import 'styles/index.css';
|
||||
@ -14,7 +13,7 @@ import '@fontsource/inter/400.css';
|
||||
import '@fontsource/inter/600.css';
|
||||
|
||||
const Intl = ({ children }) => {
|
||||
const [locale] = useLocale();
|
||||
const { locale, messages } = useLocale();
|
||||
|
||||
const Wrapper = ({ children }) => <span className={locale}>{children}</span>;
|
||||
|
||||
|
1
public/country/ar-SA.json
Normal file
1
public/country/ar-SA.json
Normal file
File diff suppressed because one or more lines are too long
1
public/country/hu-HU.json
Normal file
1
public/country/hu-HU.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user