Skip to content

Commit

Permalink
feat: add locale detecting/switching logic
Browse files Browse the repository at this point in the history
  • Loading branch information
gitlimes committed Aug 10, 2024
1 parent 3f1a58d commit fb134c4
Show file tree
Hide file tree
Showing 11 changed files with 496 additions and 223 deletions.
499 changes: 292 additions & 207 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
"private": true,
"type": "module",
"scripts": {
"dev": "NEXT_TELEMETRY_DISABLED=1 next dev",
"build": "NEXT_TELEMETRY_DISABLED=1 next build",
"start": "NEXT_TELEMETRY_DISABLED=1 next start",
"lint": "NEXT_TELEMETRY_DISABLED=1 next lint"
"dev": "NEXT_TELEMETRY_DISABLED=1 npx tsx ./src/utils/buildtime.ts && next dev",
"build": "NEXT_TELEMETRY_DISABLED=1 npx tsx ./src/utils/buildtime.ts && next build",
"start": "NEXT_TELEMETRY_DISABLED=1 npx tsx ./src/utils/buildtime.ts && next start",
"lint": "NEXT_TELEMETRY_DISABLED=1 npx tsx ./src/utils/buildtime.ts && next lint"
},
"dependencies": {
"@aws-sdk/client-ses": "^3.515.0",
"@discordjs/rest": "^0.5.0",
"@formatjs/intl-localematcher": "^0.5.4",
"@node-saml/node-saml": "^5.0.0",
"@phosphor-icons/react": "^2.1.3",
"@pretendonetwork/error-codes": "^1.0.3",
Expand All @@ -27,6 +28,7 @@
"graphql-request": "^4.3.0",
"gray-matter": "^4.0.3",
"lodash.merge": "^4.6.2",
"negotiator": "^0.6.3",
"next": "^14.2.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
130 changes: 130 additions & 0 deletions public/assets/json/localeList.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
[
{
"code": "ar-AR",
"name": "العربية (الأرجنتين)"
},
{
"code": "ast",
"name": "asturianu"
},
{
"code": "be-BY",
"name": "беларуская (Беларусь)"
},
{
"code": "ca-ES",
"name": "català (Espanya)"
},
{
"code": "cs-CZ",
"name": "čeština (Česko)"
},
{
"code": "de-DE",
"name": "Deutsch (Deutschland)"
},
{
"code": "el-GR",
"name": "Ελληνικά (Ελλάδα)"
},
{
"code": "en-GB",
"name": "British English"
},
{
"code": "en-US",
"name": "American English"
},
{
"code": "es-ES",
"name": "español de España"
},
{
"code": "fi-FI",
"name": "suomi (Suomi)"
},
{
"code": "fr-FR",
"name": "français (France)"
},
{
"code": "gd-GB",
"name": "Gàidhlig (An Rìoghachd Aonaichte)"
},
{
"code": "it-IT",
"name": "italiano (Italia)"
},
{
"code": "ja-JP",
"name": "日本語 (日本)"
},
{
"code": "kk-KZ",
"name": "қазақ тілі (Қазақстан)"
},
{
"code": "ko-KR",
"name": "한국어(대한민국)"
},
{
"code": "lt-LT",
"name": "lietuvių (Lietuva)"
},
{
"code": "nb-NO",
"name": "norsk bokmål (Norge)"
},
{
"code": "nl-NL",
"name": "Nederlands (Nederland)"
},
{
"code": "pl-PL",
"name": "polski (Polska)"
},
{
"code": "pt-BR",
"name": "português (Brasil)"
},
{
"code": "pt-PT",
"name": "português europeu"
},
{
"code": "ro-RO",
"name": "română (România)"
},
{
"code": "ru-RU",
"name": "русский (Россия)"
},
{
"code": "sr-RS",
"name": "српски (Србија)"
},
{
"code": "sv-SE",
"name": "svenska (Sverige)"
},
{
"code": "tr-TR",
"name": "Türkçe (Türkiye)"
},
{
"code": "uk-UA",
"name": "українська (Україна)"
},
{
"code": "zh-CN",
"name": "中文(中国)"
},
{
"code": "zh-Hant",
"name": "繁體中文"
},
{
"code": "en@uwu",
"name": "English (lolcat)"
}
]
2 changes: 1 addition & 1 deletion src/app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const metadata: Metadata = {
};

export default function NotFound() {
const { locale } = getLocale('TODO'); /* TODO */
const { locale } = getLocale();

return (
<ShowcaseSection
Expand Down
2 changes: 1 addition & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const metadata = {
};

export default function Home() {
const { locale } = getLocale('TODO'); /* TODO */
const { locale } = getLocale();

return (
<main>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Link from 'next/link';
import styles from './Footer.module.css';

export default function Footer() {
const { locale } = getLocale('TODO'); /* TODO */
const { locale } = getLocale();

const year = new Date().getFullYear(); /* Can't have an outdated year this way :3 */

Expand Down
2 changes: 1 addition & 1 deletion src/components/Header/HeaderWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Header from './Header';
import { getLocale, getLocaleList, localeSetter } from '@/utils/locale';

export default function HeaderWrapper() {
const { locale } = getLocale('TODO'); /* TODO */
const { locale } = getLocale();

const localeList = getLocaleList();

Expand Down
39 changes: 37 additions & 2 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,51 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

import localeList from '../public/assets/json/localeList.json';

import { isLoggedIn } from './utils/auth';

export function middleware(request: NextRequest) {
// selects locale code based on user accept-language header and saves it as cookie
let availableLocales: string[] = [];
localeList.forEach((l) => {
availableLocales.push(l.code);
});

availableLocales = availableLocales.filter((l) => l !== 'en@uwu');

const plainHeaders: Record<string, string> = {};
request.headers.forEach((v, k) => (plainHeaders[k] = v));

const userLocales = new Negotiator({ headers: plainHeaders }).languages(availableLocales);

const locale = match(userLocales, availableLocales, 'en-US');

const response = NextResponse.next();
response.cookies.set({
name: 'autoLocale',
value: locale,
path: '/',
});

if (
request.nextUrl.pathname.startsWith('/account/login') ||
request.nextUrl.pathname.startsWith('/account/register')
) {
return response;
}

if (request.nextUrl.pathname.startsWith('/account') && !isLoggedIn()) {

const target = `/account/login?redirect=${encodeURIComponent(request.nextUrl.href)}`;
return NextResponse.redirect(new URL(target, request.url));
}

return response;
}

export const config = {
matcher: '/account((?!/login|/register).*)',
matcher: '/((?!api|_next/static|_next/image|favicon.ico).*)',
};
12 changes: 12 additions & 0 deletions src/utils/buildtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* this file runs at buildtime. it should not contain any functions actively used by the website. */

import fs from 'fs-extra';
import { getLocaleList } from './locale.ts';

const filename = './public/assets/json/localeList.json';

fs.ensureFileSync(filename);

const localeList = getLocaleList();

fs.writeFileSync(filename, JSON.stringify(localeList, null, '\t'));
19 changes: 14 additions & 5 deletions src/utils/locale.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import * as fs from 'fs-extra';
import fs from 'fs-extra';
import merge from 'lodash.merge';
import logger from './logger.ts';

import baseLocale from '@/locales/en_US.json' assert { type: 'json' };

function getLocale(code: string) {
import { cookies } from 'next/headers';

function getLocale() {
const cookieStore = cookies();

const autoLocale = cookieStore.get('autoLocale')?.value;
const preferredLocale = cookieStore.get('preferredLocale')?.value;

const code = preferredLocale || autoLocale || 'us-EN';

const localeCode = code.replace('-', '_');
const path = `@/locales/${localeCode}.json`;
const path = `./locales/${localeCode}.json`;

if (fs.pathExistsSync(path)) {
const selectedLocale = JSON.parse(fs.readFileSync(path, 'utf8'));
Expand Down Expand Up @@ -53,8 +62,8 @@ function getLocaleList() {
async function localeSetter(localeCode: string) {
'use server';

// TODO: add locale setting logic
console.log(localeCode);
const cookieStore = cookies();
cookieStore.set('preferredLocale', localeCode);
}

function _localeCodeToName(localeCode: string) {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
}
]
},
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx", "src/utils/buildtime.ts"],
"exclude": ["node_modules"]
}

0 comments on commit fb134c4

Please sign in to comment.