Update localization files + references (#4556)

* Initial plan

* Add localization support to NameChangeModal component

Co-authored-by: gabek <414923+gabek@users.noreply.github.com>

* Add NameChangeModal translations to English language file

Co-authored-by: gabek <414923+gabek@users.noreply.github.com>

* fix(i18n): fix localization keys

* chore(test): add i18n test

* chore(i18n): update translation script

* chore(i18n): reorgnize translation keys and update components

* chore: fix linting warnings

* chore(i18n): update all the language files

* feat(i18n): add last live ago i18n key

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: gabek <414923+gabek@users.noreply.github.com>
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
Copilot
2025-09-15 19:27:56 -07:00
committed by GitHub
co-authored by gabek copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Gabe Kangas
parent 401b5897e2
commit 1cf923a5af
46 changed files with 6053 additions and 4639 deletions
+14 -8
View File
@@ -5,6 +5,7 @@ import { useTranslation } from 'next-export-i18n';
import { fetchData, FETCH_INTERVAL, HARDWARE_STATS } from '../../utils/apis';
import { Chart } from '../../components/admin/Chart';
import { StatisticItem } from '../../components/admin/StatisticItem';
import { Localization } from '../../types/localization';
import { AdminLayout } from '../../components/layouts/AdminLayout';
@@ -55,13 +56,13 @@ export default function HardwareInfo() {
if (!hardwareStatus.cpu) {
return (
<div>
<Typography.Title>{t('Hardware Info')}</Typography.Title>
<Typography.Title>{t(Localization.Admin.HardwareInfo.title)}</Typography.Title>
<Alert
style={{ marginTop: '10px' }}
banner
message={t('Please wait')}
description={t('No hardware details have been collected yet.')}
message={t(Localization.Admin.HardwareInfo.pleaseWait)}
description={t(Localization.Admin.HardwareInfo.noDetails)}
type="info"
/>
<Spin spinning style={{ width: '100%', margin: '10px' }} />
@@ -75,19 +76,19 @@ export default function HardwareInfo() {
const series = [
{
name: t('CPU'),
name: t(Localization.Admin.HardwareInfo.cpu),
color: '#B63FFF',
data: hardwareStatus.cpu,
pointStyle: 'rect',
},
{
name: t('Memory'),
name: t(Localization.Admin.HardwareInfo.memory),
color: '#2087E2',
data: hardwareStatus.memory,
pointStyle: 'circle',
},
{
name: t('Disk'),
name: t(Localization.Admin.HardwareInfo.disk),
color: '#FF7700',
data: hardwareStatus.disk,
pointStyle: 'rectRounded',
@@ -96,7 +97,7 @@ export default function HardwareInfo() {
return (
<>
<Typography.Title>{t('Hardware Info')}</Typography.Title>
<Typography.Title>{t(Localization.Admin.HardwareInfo.title)}</Typography.Title>
<br />
<div>
<Row gutter={[16, 16]} justify="space-around">
@@ -132,7 +133,12 @@ export default function HardwareInfo() {
</Col>
</Row>
<Chart title={`% ${t('used')}`} dataCollections={series} color="#FF7700" unit="%" />
<Chart
title={`% ${t(Localization.Admin.HardwareInfo.used)}`}
dataCollections={series}
color="#FF7700"
unit="%"
/>
</div>
</>
);
+31 -30
View File
@@ -6,6 +6,7 @@ import React, { ReactElement } from 'react';
import dynamic from 'next/dynamic';
import { useTranslation } from 'next-export-i18n';
import { Localization } from '../../types/localization';
import { AdminLayout } from '../../components/layouts/AdminLayout';
// Lazy loaded components
@@ -56,7 +57,7 @@ export default function Help() {
const questions = [
{
icon: <SettingTwoTone style={{ fontSize: '24px' }} />,
title: t('I want to configure my owncast instance'),
title: t(Localization.Admin.Help.configureInstance),
content: (
<div>
<a
@@ -64,14 +65,14 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
},
{
icon: <CameraTwoTone style={{ fontSize: '24px' }} />,
title: t('Help configuring my broadcasting software'),
title: t(Localization.Admin.Help.configureBroadcasting),
content: (
<div>
<a
@@ -79,14 +80,14 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
},
{
icon: <Html5TwoTone style={{ fontSize: '24px' }} />,
title: t('I want to embed my stream into another site'),
title: t(Localization.Admin.Help.embedStream),
content: (
<div>
<a
@@ -94,14 +95,14 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
},
{
icon: <EditTwoTone style={{ fontSize: '24px' }} />,
title: t('I want to customize my website'),
title: t(Localization.Admin.Help.customizeWebsite),
content: (
<div>
<a
@@ -109,14 +110,14 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
},
{
icon: <SlidersTwoTone style={{ fontSize: '24px' }} />,
title: t('I want to tweak my video output'),
title: t(Localization.Admin.Help.tweakVideo),
content: (
<div>
<a
@@ -124,14 +125,14 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
},
{
icon: <DatabaseTwoTone style={{ fontSize: '24px' }} />,
title: t('I want to use an external storage provider'),
title: t(Localization.Admin.Help.useStorage),
content: (
<div>
<a
@@ -139,7 +140,7 @@ export default function Help() {
target="_blank"
rel="noopener noreferrer"
>
<LinkOutlined /> {t('Learn more')}
<LinkOutlined /> {t(Localization.Admin.Help.learnMore)}
</a>
</div>
),
@@ -149,58 +150,58 @@ export default function Help() {
const otherResources = [
{
icon: <BugTwoTone style={{ fontSize: '24px' }} />,
title: t('I found a bug'),
title: t(Localization.Admin.Help.foundBug),
content: (
<div>
{t('If you found a bug, then please')}
{t(Localization.Admin.Help.bugPlease)}
<a
href="https://github.com/owncast/owncast/issues/new/choose"
target="_blank"
rel="noopener noreferrer"
>
{' '}
{t('let us know')}
{t(Localization.Admin.Help.letUsKnow)}
</a>
</div>
),
},
{
icon: <QuestionCircleTwoTone style={{ fontSize: '24px' }} />,
title: t('I have a general question'),
title: t(Localization.Admin.Help.generalQuestion),
content: (
<div>
{t('Most general questions are answered in our')}
{t(Localization.Admin.Help.generalAnswered)}
<a
href="https://owncast.online/faq/?source=admin"
target="_blank"
rel="noopener noreferrer"
>
{' '}
{t('FAQ')}
{t(Localization.Admin.Help.faq)}
</a>{' '}
{t('or exist in our')}{' '}
{t(Localization.Admin.Help.orExist)}{' '}
<a
href="https://github.com/owncast/owncast/discussions"
target="_blank"
rel="noopener noreferrer"
>
{t('discussions')}
{t(Localization.Admin.Help.discussions)}
</a>
</div>
),
},
{
icon: <ApiTwoTone style={{ fontSize: '24px' }} />,
title: t('I want to build add-ons for Owncast'),
title: t(Localization.Admin.Help.buildAddons),
content: (
<div>
{t('You can build your own bots, overlays, tools and add-ons with our')}
{t(Localization.Admin.Help.buildTools)}
<a
href="https://owncast.online/thirdparty?source=admin"
target="_blank"
rel="noopener noreferrer"
>
&nbsp;{t('developer APIs.')}&nbsp;
&nbsp;{t(Localization.Admin.Help.developerApis)}&nbsp;
</a>
</div>
),
@@ -209,11 +210,11 @@ export default function Help() {
return (
<div className="help-page">
<Title style={{ textAlign: 'center' }}>{t('How can we help you?')}</Title>
<Title style={{ textAlign: 'center' }}>{t(Localization.Admin.Help.title)}</Title>
<Row gutter={[16, 16]} justify="space-around" align="middle">
<Col xs={24} lg={12} style={{ textAlign: 'center' }}>
<Result status="500" />
<Title level={2}>{t('Troubleshooting')}</Title>
<Title level={2}>{t(Localization.Admin.Help.troubleshooting)}</Title>
<Button
target="_blank"
rel="noopener noreferrer"
@@ -221,12 +222,12 @@ export default function Help() {
icon={<LinkOutlined />}
type="primary"
>
{t('Fix your problems')}
{t(Localization.Admin.Help.fixProblems)}
</Button>
</Col>
<Col xs={24} lg={12} style={{ textAlign: 'center' }}>
<Result status="404" />
<Title level={2}>{t('Documentation')}</Title>
<Title level={2}>{t(Localization.Admin.Help.documentation)}</Title>
<Button
target="_blank"
rel="noopener noreferrer"
@@ -234,12 +235,12 @@ export default function Help() {
icon={<LinkOutlined />}
type="primary"
>
{t('Read the Docs')}
{t(Localization.Admin.Help.readDocs)}
</Button>
</Col>
</Row>
<Divider />
<Title level={2}>{t('Common tasks')}</Title>
<Title level={2}>{t(Localization.Admin.Help.commonTasks)}</Title>
<Row gutter={[16, 16]}>
{questions.map(question => (
<Col xs={24} lg={12} key={question.title}>
@@ -250,7 +251,7 @@ export default function Help() {
))}
</Row>
<Divider />
<Title level={2}>{t('Other')}</Title>
<Title level={2}>{t(Localization.Admin.Help.other)}</Title>
<Row gutter={[16, 16]}>
{otherResources.map(question => (
<Col xs={24} lg={12} key={question.title}>
+19 -14
View File
@@ -12,6 +12,7 @@ import { ServerStatusContext } from '../../utils/server-status-context';
import { VIEWERS_OVER_TIME, ACTIVE_VIEWER_DETAILS, fetchData } from '../../utils/apis';
import { AdminLayout } from '../../components/layouts/AdminLayout';
import { Localization } from '../../types/localization';
// Lazy loaded components
@@ -36,13 +37,13 @@ export default function ViewersOverTime() {
}
const times = [
{ title: t('Current stream'), start: streamStart },
{ title: t('Last 12 hours'), start: sub(new Date(), { hours: 12 }) },
{ title: t('Last 24 hours'), start: sub(new Date(), { hours: 24 }) },
{ title: t('Last 7 days'), start: sub(new Date(), { days: 7 }) },
{ title: t('Last 30 days'), start: sub(new Date(), { days: 30 }) },
{ title: t('Last 3 months'), start: sub(new Date(), { months: 3 }) },
{ title: t('Last 6 months'), start: sub(new Date(), { months: 6 }) },
{ title: t(Localization.Admin.ViewerInfo.currentStream), start: streamStart },
{ title: t(Localization.Admin.ViewerInfo.last12Hours), start: sub(new Date(), { hours: 12 }) },
{ title: t(Localization.Admin.ViewerInfo.last24Hours), start: sub(new Date(), { hours: 24 }) },
{ title: t(Localization.Admin.ViewerInfo.last7Days), start: sub(new Date(), { days: 7 }) },
{ title: t(Localization.Admin.ViewerInfo.last30Days), start: sub(new Date(), { days: 30 }) },
{ title: t(Localization.Admin.ViewerInfo.last3Months), start: sub(new Date(), { months: 3 }) },
{ title: t(Localization.Admin.ViewerInfo.last6Months), start: sub(new Date(), { months: 6 }) },
];
const [loadingChart, setLoadingChart] = useState(true);
@@ -96,13 +97,13 @@ export default function ViewersOverTime() {
return (
<>
<Typography.Title>{t('Viewer Info')}</Typography.Title>
<Typography.Title>{t(Localization.Admin.ViewerInfo.title)}</Typography.Title>
<br />
<Row gutter={[16, 16]} justify="space-around">
{online && (
<Col span={8} md={8}>
<StatisticItem
title={t('Current viewers')}
title={t(Localization.Admin.ViewerInfo.currentViewers)}
value={viewerCount.toString()}
prefix={<UserOutlined />}
/>
@@ -110,14 +111,18 @@ export default function ViewersOverTime() {
)}
<Col md={online ? 8 : 12}>
<StatisticItem
title={online ? t('Max viewers this stream') : t('Max viewers last stream')}
title={
online
? t(Localization.Admin.ViewerInfo.maxViewersThisStream)
: t(Localization.Admin.ViewerInfo.maxViewersLastStream)
}
value={sessionPeakViewerCount.toString()}
prefix={<UserOutlined />}
/>
</Col>
<Col md={online ? 8 : 12}>
<StatisticItem
title={t('max viewers')}
title={t(Localization.Admin.ViewerInfo.maxViewers)}
value={overallPeakViewerCount.toString()}
prefix={<UserOutlined />}
/>
@@ -127,8 +132,8 @@ export default function ViewersOverTime() {
<Alert
style={{ marginTop: '10px' }}
banner
message={t('Please wait')}
description={t('No viewer data has been collected yet.')}
message={t(Localization.Admin.ViewerInfo.pleaseWait)}
description={t(Localization.Admin.ViewerInfo.noData)}
type="info"
/>
)}
@@ -136,7 +141,7 @@ export default function ViewersOverTime() {
<Spin spinning={!viewerInfo.length || loadingChart}>
{viewerInfo.length > 0 && (
<Chart
title={t('Viewers')}
title={t(Localization.Admin.ViewerInfo.viewers)}
data={viewerInfo}
color="#2087E2"
unit="viewers"