messages/en.json | 58 ++++++++++++
messages/ja.json | 58 ++++++++++++
messages/translation-todo.json | 202 +++++++++++++++++++++++++++++++++++++++++
next-env.d.ts | 1 +
next.config.js | 5 +-
package.json | 3 +-
src/app/components/page.tsx | 159 ++++++++++++++++----------------
src/app/error.tsx | 6 +-
src/app/layout.tsx | 9 +-
src/app/not-found.tsx | 6 +-
src/app/page.tsx | 10 +-
src/i18n/request.ts | 11 +++
12 files changed, 435 insertions(+), 93 deletions(-)
diff --git a/messages/en.json b/messages/en.json
new file mode 100644
index 0000000..e43f619
--- /dev/null
+++ b/messages/en.json
@@ -0,0 +1,58 @@
+{
+ "error": {
+ "oops_something_went_wrong": "Oops, something went wrong!",
+ "try_again": "Try again"
+ },
+ "not_found": {
+ "back_to_home": "Back to home",
+ "page_not_found": "Page Not Found"
+ },
+ "page": {
+ "add_styling_on_top_of_unstyledlink_givin": "Add styling on top of UnstyledLink, giving a primary color to the link.",
+ "add_styling_on_top_of_unstyledlink_givin_2": "Add styling on top of UnstyledLink, giving a dotted and animated underline.",
+ "arrowlink": "ArrowLink",
+ "back_to_home": "Back to Home",
+ "basic_variant": "Basic Variant",
+ "built_in_components": "Built-in Components",
+ "button": "Button",
+ "button_styled_link_with_3_variants": "Button styled link with 3 variants.",
+ "button_with_a_text_style": "Button with a text style",
+ "button_with_only_icon_inside": "Button with only icon inside",
+ "buttonlink": "ButtonLink",
+ "check_list_of_colors": "Check list of colors",
+ "custom_404_page": "Custom 404 Page",
+ "customize_colors": "Customize Colors",
+ "dark_variant": "Dark Variant",
+ "deploy_with_vercel": "Deploy with Vercel",
+ "direction_left": "Direction Left",
+ "direction_right": "Direction Right",
+ "disabled": "Disabled",
+ "ghost_variant": "Ghost Variant",
+ "icon": "Icon",
+ "iconbutton": "IconButton",
+ "internal_links": "Internal Links",
+ "light_variant": "Light Variant",
+ "next_image": "Next Image",
+ "next_image_with_default_props_and_skelet": "Next Image with default props and skeleton animation",
+ "next_js_tailwind_css_typescript_starter": "Next.js + Tailwind CSS + TypeScript Starter",
+ "no_style_applied_differentiate_internal": "No style applied, differentiate internal and outside links, give custom cursor for outside links.",
+ "ordinary_button_with_style": "Ordinary button with style.",
+ "outline_variant": "Outline Variant",
+ "outside_links": "Outside Links",
+ "polymorphic": "Polymorphic",
+ "primary_variant": "Primary Variant",
+ "primarylink": "PrimaryLink",
+ "see_all_components": "See all components",
+ "see_the_repository": "See the repository",
+ "skeleton": "Skeleton",
+ "skeleton_with_shimmer_effect": "Skeleton with shimmer effect",
+ "small_size": "Small Size",
+ "styled_404_page_with_some_animation": "Styled 404 page with some animation.",
+ "textbutton": "TextButton",
+ "underlinelink": "UnderlineLink",
+ "unstyledlink": "UnstyledLink",
+ "useful_for_indicating_navigation_i_use_t": "Useful for indicating navigation, I use this quite a lot, so why not build a component with some whimsy touch?",
+ "visit_the_404_page": "Visit the 404 page",
+ "you_can_change_primary_color_to_any_tail": "You can change primary color to any Tailwind CSS colors. See globals.css to change your color."
+ }
+}
diff --git a/messages/ja.json b/messages/ja.json
new file mode 100644
index 0000000..e43f619
--- /dev/null
+++ b/messages/ja.json
@@ -0,0 +1,58 @@
+{
+ "error": {
+ "oops_something_went_wrong": "Oops, something went wrong!",
+ "try_again": "Try again"
+ },
+ "not_found": {
+ "back_to_home": "Back to home",
+ "page_not_found": "Page Not Found"
+ },
+ "page": {
+ "add_styling_on_top_of_unstyledlink_givin": "Add styling on top of UnstyledLink, giving a primary color to the link.",
+ "add_styling_on_top_of_unstyledlink_givin_2": "Add styling on top of UnstyledLink, giving a dotted and animated underline.",
+ "arrowlink": "ArrowLink",
+ "back_to_home": "Back to Home",
+ "basic_variant": "Basic Variant",
+ "built_in_components": "Built-in Components",
+ "button": "Button",
+ "button_styled_link_with_3_variants": "Button styled link with 3 variants.",
+ "button_with_a_text_style": "Button with a text style",
+ "button_with_only_icon_inside": "Button with only icon inside",
+ "buttonlink": "ButtonLink",
+ "check_list_of_colors": "Check list of colors",
+ "custom_404_page": "Custom 404 Page",
+ "customize_colors": "Customize Colors",
+ "dark_variant": "Dark Variant",
+ "deploy_with_vercel": "Deploy with Vercel",
+ "direction_left": "Direction Left",
+ "direction_right": "Direction Right",
+ "disabled": "Disabled",
+ "ghost_variant": "Ghost Variant",
+ "icon": "Icon",
+ "iconbutton": "IconButton",
+ "internal_links": "Internal Links",
+ "light_variant": "Light Variant",
+ "next_image": "Next Image",
+ "next_image_with_default_props_and_skelet": "Next Image with default props and skeleton animation",
+ "next_js_tailwind_css_typescript_starter": "Next.js + Tailwind CSS + TypeScript Starter",
+ "no_style_applied_differentiate_internal": "No style applied, differentiate internal and outside links, give custom cursor for outside links.",
+ "ordinary_button_with_style": "Ordinary button with style.",
+ "outline_variant": "Outline Variant",
+ "outside_links": "Outside Links",
+ "polymorphic": "Polymorphic",
+ "primary_variant": "Primary Variant",
+ "primarylink": "PrimaryLink",
+ "see_all_components": "See all components",
+ "see_the_repository": "See the repository",
+ "skeleton": "Skeleton",
+ "skeleton_with_shimmer_effect": "Skeleton with shimmer effect",
+ "small_size": "Small Size",
+ "styled_404_page_with_some_animation": "Styled 404 page with some animation.",
+ "textbutton": "TextButton",
+ "underlinelink": "UnderlineLink",
+ "unstyledlink": "UnstyledLink",
+ "useful_for_indicating_navigation_i_use_t": "Useful for indicating navigation, I use this quite a lot, so why not build a component with some whimsy touch?",
+ "visit_the_404_page": "Visit the 404 page",
+ "you_can_change_primary_color_to_any_tail": "You can change primary color to any Tailwind CSS colors. See globals.css to change your color."
+ }
+}
diff --git a/messages/translation-todo.json b/messages/translation-todo.json
new file mode 100644
index 0000000..657b057
--- /dev/null
+++ b/messages/translation-todo.json
@@ -0,0 +1,202 @@
+[
+ {
+ "key": "error.oops_something_went_wrong",
+ "en": "Oops, something went wrong!"
+ },
+ {
+ "key": "error.try_again",
+ "en": "Try again"
+ },
+ {
+ "key": "not_found.back_to_home",
+ "en": "Back to home"
+ },
+ {
+ "key": "not_found.page_not_found",
+ "en": "Page Not Found"
+ },
+ {
+ "key": "page.add_styling_on_top_of_unstyledlink_givin",
+ "en": "Add styling on top of UnstyledLink, giving a primary color to the link."
+ },
+ {
+ "key": "page.add_styling_on_top_of_unstyledlink_givin_2",
+ "en": "Add styling on top of UnstyledLink, giving a dotted and animated underline."
+ },
+ {
+ "key": "page.arrowlink",
+ "en": "ArrowLink"
+ },
+ {
+ "key": "page.back_to_home",
+ "en": "Back to Home"
+ },
+ {
+ "key": "page.basic_variant",
+ "en": "Basic Variant"
+ },
+ {
+ "key": "page.built_in_components",
+ "en": "Built-in Components"
+ },
+ {
+ "key": "page.button",
+ "en": "Button"
+ },
+ {
+ "key": "page.button_styled_link_with_3_variants",
+ "en": "Button styled link with 3 variants."
+ },
+ {
+ "key": "page.button_with_a_text_style",
+ "en": "Button with a text style"
+ },
+ {
+ "key": "page.button_with_only_icon_inside",
+ "en": "Button with only icon inside"
+ },
+ {
+ "key": "page.buttonlink",
+ "en": "ButtonLink"
+ },
+ {
+ "key": "page.check_list_of_colors",
+ "en": "Check list of colors"
+ },
+ {
+ "key": "page.custom_404_page",
+ "en": "Custom 404 Page"
+ },
+ {
+ "key": "page.customize_colors",
+ "en": "Customize Colors"
+ },
+ {
+ "key": "page.dark_variant",
+ "en": "Dark Variant"
+ },
+ {
+ "key": "page.deploy_with_vercel",
+ "en": "Deploy with Vercel"
+ },
+ {
+ "key": "page.direction_left",
+ "en": "Direction Left"
+ },
+ {
+ "key": "page.direction_right",
+ "en": "Direction Right"
+ },
+ {
+ "key": "page.disabled",
+ "en": "Disabled"
+ },
+ {
+ "key": "page.ghost_variant",
+ "en": "Ghost Variant"
+ },
+ {
+ "key": "page.icon",
+ "en": "Icon"
+ },
+ {
+ "key": "page.iconbutton",
+ "en": "IconButton"
+ },
+ {
+ "key": "page.internal_links",
+ "en": "Internal Links"
+ },
+ {
+ "key": "page.light_variant",
+ "en": "Light Variant"
+ },
+ {
+ "key": "page.next_image",
+ "en": "Next Image"
+ },
+ {
+ "key": "page.next_image_with_default_props_and_skelet",
+ "en": "Next Image with default props and skeleton animation"
+ },
+ {
+ "key": "page.next_js_tailwind_css_typescript_starter",
+ "en": "Next.js + Tailwind CSS + TypeScript Starter"
+ },
+ {
+ "key": "page.no_style_applied_differentiate_internal",
+ "en": "No style applied, differentiate internal and outside links, give custom cursor for outside links."
+ },
+ {
+ "key": "page.ordinary_button_with_style",
+ "en": "Ordinary button with style."
+ },
+ {
+ "key": "page.outline_variant",
+ "en": "Outline Variant"
+ },
+ {
+ "key": "page.outside_links",
+ "en": "Outside Links"
+ },
+ {
+ "key": "page.polymorphic",
+ "en": "Polymorphic"
+ },
+ {
+ "key": "page.primary_variant",
+ "en": "Primary Variant"
+ },
+ {
+ "key": "page.primarylink",
+ "en": "PrimaryLink"
+ },
+ {
+ "key": "page.see_all_components",
+ "en": "See all components"
+ },
+ {
+ "key": "page.see_the_repository",
+ "en": "See the repository"
+ },
+ {
+ "key": "page.skeleton",
+ "en": "Skeleton"
+ },
+ {
+ "key": "page.skeleton_with_shimmer_effect",
+ "en": "Skeleton with shimmer effect"
+ },
+ {
+ "key": "page.small_size",
+ "en": "Small Size"
+ },
+ {
+ "key": "page.styled_404_page_with_some_animation",
+ "en": "Styled 404 page with some animation."
+ },
+ {
+ "key": "page.textbutton",
+ "en": "TextButton"
+ },
+ {
+ "key": "page.underlinelink",
+ "en": "UnderlineLink"
+ },
+ {
+ "key": "page.unstyledlink",
+ "en": "UnstyledLink"
+ },
+ {
+ "key": "page.useful_for_indicating_navigation_i_use_t",
+ "en": "Useful for indicating navigation, I use this quite a lot, so why not build a component with some whimsy touch?"
+ },
+ {
+ "key": "page.visit_the_404_page",
+ "en": "Visit the 404 page"
+ },
+ {
+ "key": "page.you_can_change_primary_color_to_any_tail",
+ "en": "You can change primary color to any Tailwind CSS colors. See globals.css to change your color."
+ }
+]
diff --git a/next-env.d.ts b/next-env.d.ts
index 1b3be08..830fb59 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,5 +1,6 @@
///
///
+///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/next.config.js b/next.config.js
index 6a4c4b4..91ae849 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,3 +1,6 @@
+const createNextIntlPlugin = require('next-intl/plugin');
+const withNextIntl = createNextIntlPlugin();
+
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
@@ -49,4 +52,4 @@ const nextConfig = {
},
};
-module.exports = nextConfig;
+module.exports = withNextIntl(nextConfig);
diff --git a/package.json b/package.json
index 429309f..6bb22fb 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,8 @@
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^2.6.0",
- "zod": "^3.24.1"
+ "zod": "^3.24.1",
+ "next-intl": "^4.0.0"
},
"devDependencies": {
"@commitlint/cli": "^16.3.0",
diff --git a/src/app/components/page.tsx b/src/app/components/page.tsx
index 393fff8..fb0ac63 100644
--- a/src/app/components/page.tsx
+++ b/src/app/components/page.tsx
@@ -1,4 +1,5 @@
'use client';
+import { useTranslations } from 'next-intl';
import clsx from 'clsx';
import {
@@ -25,6 +26,7 @@ import Skeleton from '@/components/Skeleton';
type Color = (typeof colorList)[number];
export default function ComponentPage() {
+ const t = useTranslations();
const [mode, setMode] = React.useState<'dark' | 'light'>('light');
const [color, setColor] = React.useState('sky');
function toggleMode() {
@@ -44,9 +46,9 @@ export default function ComponentPage() {
mode === 'dark' ? 'text-white' : 'text-black'
)}
>
-
Built-in Components
+
{t('page.built_in_components')}
- Back to Home
+ {t('page.back_to_home')}
@@ -61,10 +63,9 @@ export default function ComponentPage() {
-
Customize Colors
+
{t('page.customize_colors')}
- You can change primary color to any Tailwind CSS colors. See
- globals.css to change your color.
+ {t('page.you_can_change_primary_color_to_any_tail')}
@@ -127,61 +128,57 @@ export default function ComponentPage() {
-
UnstyledLink
+
{t('page.unstyledlink')}
- No style applied, differentiate internal and outside links, give
- custom cursor for outside links.
+ {t('page.no_style_applied_differentiate_internal')}
- Useful for indicating navigation, I use this quite a lot, so why
- not build a component with some whimsy touch?
+ {t('page.useful_for_indicating_navigation_i_use_t')}
- Direction Left
+ {t('page.direction_left')}
- Direction Right
+ {t('page.direction_right')}
- Polymorphic
+ {t('page.polymorphic')}
- Polymorphic
+ {t('page.polymorphic')}
-
ButtonLink
+
{t('page.buttonlink')}
- Button styled link with 3 variants.
+ {t('page.button_styled_link_with_3_variants')}
A starter for Next.js, Tailwind CSS, and TypeScript with Absolute
Import, Seo, Link component, pre-configured with Husky{' '}
- See the repository
+ {t('page.see_the_repository')}
- See all components
+ {t('page.see_all_components')}
diff --git a/src/i18n/request.ts b/src/i18n/request.ts
new file mode 100644
index 0000000..eb85a4b
--- /dev/null
+++ b/src/i18n/request.ts
@@ -0,0 +1,11 @@
+import { getRequestConfig } from 'next-intl/server';
+
+// Single-locale setup (no locale routing): the agent localizes the code and seeds the
+// messages; negotiating / switching the active locale is left to the team.
+export default getRequestConfig(async () => {
+ const locale = 'en';
+ return {
+ locale,
+ messages: (await import(`../../messages/${locale}.json`)).default,
+ };
+});