I18n orgId/settings (#21)

* New translation keys in en-US locale

* New translation keys in de-DE locale

* New translation keys in fr-FR locale

* New translation keys in it-IT locale

* New translation keys in pl-PL locale

* New translation keys in pt-PT locale

* New translation keys in tr-TR locale

* Add translation keys if settings/resources/resourceId/authentication

* New translation keys in en-US locale

* New translation keys in de-DE locale

* New translation keys in fr-FR locale

* New translation keys in it-IT locale

* New translation keys in pl-PL locale

* New translation keys in pt-PT locale

* New translation keys in tr-TR locale

* Add translation keys if settings/resources/resourceId/general

* Small naming fix

* New translation keys in en-US locale

* New translation keys in de-DE locale

* New translation keys in fr-FR locale

* New translation keys in it-IT locale

* New translation keys in pl-PL locale

* New translation keys in pt-PT locale

* New translation keys in tr-TR locale

* Add translation keys if settings/access/roles

* New translation keys in en-US locale

* New translation keys in de-DE locale

* New translation keys in fr-FR locale

* New translation keys in it-IT locale

* New translation keys in pl-PL locale

* New translation keys in pt-PT locale

* New translation keys in tr-TR locale

* Add translation keys in orgId/settings

* Fixes after merge

* Fixes after merge

* Fixes after merge

* Small fix

* Fix build
This commit is contained in:
vlalx
2025-05-17 18:49:01 +03:00
committed by GitHub
parent 6f54e3da9e
commit 96bfc3cf36
49 changed files with 2749 additions and 590 deletions

View File

@@ -52,16 +52,14 @@ import {
import LoaderPlaceholder from "@app/components/PlaceHolderLoader";
import { useTranslations } from 'next-intl';
const t = useTranslations();
const createSiteFormSchema = z.object({
name: z
.string()
.min(2, {
message: {t('siteNameMin')}
message: "Name must be at least 2 characters."
})
.max(30, {
message: {t('siteNameMax')}
message: "Name must not be longer than 30 characters."
}),
method: z.enum(["wireguard", "newt", "local"])
});
@@ -117,6 +115,8 @@ export default function CreateSiteForm({
const nameField = form.watch("name");
const methodField = form.watch("method");
const t = useTranslations();
useEffect(() => {
const nameIsValid = nameField?.length >= 2 && nameField?.length <= 30;
const isFormValid = methodField === "local" || isChecked;
@@ -172,8 +172,8 @@ export default function CreateSiteForm({
if (!keypair || !siteDefaults) {
toast({
variant: "destructive",
title: {t('siteErrorCreate')},
description: {t('siteErrorCreateKeyPair')}
title: "Error creating site",
description: "Key pair or site defaults not found"
});
setLoading?.(false);
setIsLoading(false);
@@ -191,8 +191,8 @@ export default function CreateSiteForm({
if (!siteDefaults) {
toast({
variant: "destructive",
title: {t('siteErrorCreate')},
description: {t('siteErrorCreateDefaults')}
title: "Error creating site",
description: "Site defaults not found"
});
setLoading?.(false);
setIsLoading(false);
@@ -215,7 +215,7 @@ export default function CreateSiteForm({
.catch((e) => {
toast({
variant: "destructive",
title: {t('siteErrorCreate')},
title: "Error creating site",
description: formatAxiosError(e)
});
});
@@ -315,7 +315,7 @@ PersistentKeepalive = 5`
</SelectTrigger>
<SelectContent>
<SelectItem value="local">
Local
{t('local')}
</SelectItem>
<SelectItem
value="newt"

View File

@@ -22,8 +22,8 @@ export function SitesDataTable<TData, TValue>({
<DataTable
columns={columns}
data={data}
title="Sites"
searchPlaceholder={t('searchSites')}
title={t('sites')}
searchPlaceholder={t('searchSitesProgress')}
searchColumn="name"
onAdd={createSite}
addButtonText={t('siteAdd')}

View File

@@ -36,7 +36,7 @@ export const SitesSplashCard = () => {
<button
onClick={handleDismiss}
className="absolute top-2 right-2 p-2"
aria-label="Dismiss"
aria-label={t('dismiss')}
>
<X className="w-5 h-5" />
</button>
@@ -70,7 +70,7 @@ export const SitesSplashCard = () => {
className="w-full flex items-center"
variant="secondary"
>
Install Newt{" "}
{t('siteInstallNewt')}{" "}
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</Link>
@@ -78,20 +78,19 @@ export const SitesSplashCard = () => {
</div>
<div className="space-y-4">
<h3 className="text-xl font-semibold flex items-center gap-2">
Basic WireGuard
{t('siteWg')}
</h3>
<p className="text-sm">
Use any WireGuard client to connect. You will have to
address your internal resources using the peer IP.
{t('siteWgAnyClients')}
</p>
<ul className="text-sm text-muted-foreground space-y-2">
<li className="flex items-center gap-2">
<Docker className="text-purple-500 w-4 h-4" />
Compatible with all WireGuard clients
{t('siteWgCompatibleAllClients')}
</li>
<li className="flex items-center gap-2">
<Server className="text-purple-500 w-4 h-4" />
Manual configuration required
{t('siteWgManualConfigurationRequired')}
</li>
</ul>
</div>

View File

@@ -25,7 +25,7 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
} else if (type === "local") {
return t('local');
} else {
return "Unknown";
return t('unknown');
}
};

View File

@@ -47,7 +47,6 @@ export default function GeneralPage() {
const [loading, setLoading] = useState(false);
const router = useRouter();
const t = useTranslations();
const form = useForm<GeneralFormValues>({
resolver: zodResolver(GeneralFormSchema),
@@ -56,6 +55,7 @@ export default function GeneralPage() {
},
mode: "onChange"
});
const t = useTranslations();
async function onSubmit(data: GeneralFormValues) {
setLoading(true);
@@ -67,16 +67,19 @@ export default function GeneralPage() {
.catch((e) => {
toast({
variant: "destructive",
title: t('siteErrorUpdate'),
description: formatAxiosError(e,t('siteErrorUpdateDescription'))
title: "Failed to update site",
description: formatAxiosError(
e,
"An error occurred while updating the site."
)
});
});
updateSite({ name: data.name });
toast({
title: t('siteUpdated'),
description: t('siteUpdatedDescription')
title: "Site updated",
description: "The site has been updated."
});
setLoading(false);

View File

@@ -70,7 +70,7 @@ const createSiteFormSchema = z
.object({
name: z
.string()
.min(2, { message: "Name must be at least 2 characters." })
.min(2, "Name must be at least 2 characters.")
.max(30, {
message: "Name must not be longer than 30 characters."
}),
@@ -324,7 +324,7 @@ WantedBy=default.target`
};
const getCommand = () => {
const placeholder = ["Unknown command"];
const placeholder = [t('unknownCommand')];
if (!commands) {
return placeholder;
}
@@ -381,8 +381,8 @@ WantedBy=default.target`
if (!siteDefaults || !wgConfig) {
toast({
variant: "destructive",
title: t('siteErrorCreate'),
description: t('siteErrorCreateKeyPair')
title: "Error creating site",
description: "Key pair or site defaults not found"
});
setCreateLoading(false);
return;
@@ -399,8 +399,8 @@ WantedBy=default.target`
if (!siteDefaults) {
toast({
variant: "destructive",
title: t('siteErrorCreate'),
description: t('siteErrorCreateDefaults')
title: "Error creating site",
description: "Site defaults not found"
});
setCreateLoading(false);
return;
@@ -422,7 +422,7 @@ WantedBy=default.target`
.catch((e) => {
toast({
variant: "destructive",
title: t('siteErrorCreate'),
title: "Error creating site",
description: formatAxiosError(e)
});
});
@@ -448,14 +448,14 @@ WantedBy=default.target`
);
if (!response.ok) {
throw new Error(
`Failed to fetch release info: ${response.statusText}`
t('newtErrorFetchReleases', {err: response.statusText})
);
}
const data = await response.json();
const latestVersion = data.tag_name;
newtVersion = latestVersion;
} catch (error) {
console.error("Error fetching latest release:", error);
console.error(t('newtErrorFetchLatest', {err: error instanceof Error ? error.message : String(error)}));
}
const generatedKeypair = generateKeypair();
@@ -612,7 +612,7 @@ WantedBy=default.target`
<InfoSections cols={3}>
<InfoSection>
<InfoSectionTitle>
Newt Endpoint
{t('newtEndpoint')}
</InfoSectionTitle>
<InfoSectionContent>
<CopyToClipboard
@@ -624,7 +624,7 @@ WantedBy=default.target`
</InfoSection>
<InfoSection>
<InfoSectionTitle>
Newt ID
{t('newtId')}
</InfoSectionTitle>
<InfoSectionContent>
<CopyToClipboard
@@ -634,7 +634,7 @@ WantedBy=default.target`
</InfoSection>
<InfoSection>
<InfoSectionTitle>
Newt Secret Key
{t('newtSecretKey')}
</InfoSectionTitle>
<InfoSectionContent>
<CopyToClipboard
@@ -737,8 +737,8 @@ WantedBy=default.target`
{["docker", "podman"].includes(
platform
)
? "Method"
: "Architecture"}
? t('method')
: t('architecture')}
</p>
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
{getArchitectures().map(