1.1.1 • Published 7 months ago

nextjs-static-page-localizer v1.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

NEXT.js Static Page Localizer

npm version npm Package Quality

What this offers

  • Localization for your NEXT.js app
  • Static Web App compatible
  • Configurable
  • Customizable UI-components
  • Flexibility
  • Head Title and Description Localization

Introduction

This is a package for creating localized NEXT.js applications that runs as Static Web Pages. While static web pages are cheap, easy to use and great, they lack some functionality to support some of the more poular localization packages.

We have created this package to help users easily introduce localization on their web apps as easily as possible. Keep on reading to learn more of how this works.

How to Use

Get Started Easily

If you want to create a new project using this package, head over to the template project we've created.

Install

npm i nextjs-static-page-localizer

Add required files

While technically you don't need to add extra files to your project for this, it is advisable to do so in order to keep your project more easily navigable, maintainable and easier to work with. Following from here, we will use our prefered way of setting this up, which closely resembles the way in which other localization/internationalization packages use.

At your root you need to create a folder called messages and this should contain a file called config.json and a .json file for each language you aim to support.

Configure config.json

You should configure the config file as shown under. You need to specify a default language (specified by code) and then all the languages you support (including default). The languages need to be specified with code and name.

{
    "default": "en",
    "languages": [
        {
            "code": "en",
            "name": "English"
        },
        {
            "code": "fr",
            "name": "French"
        }
    ]
}

Configure a Language file

Each language file should be on the format <code>.json and placed in the messages folder, where <code> is the same as the code of the language in the config.json file.

{
    "home": {
        "title": "Hello!",
        "welcome": "Welcome traveler! Be a guest on my site!"
    },
    "some-section": {
        "some-field": "Some content",
        "some-other-field": "Some other content"
    },
    // Under is specifically for metadata, which has a kinda protected name
    "metadata": {
        "home-title": "Title on home-page",
        "home-description": "This is a description of the home page",
        "some-section-title": "Some other title", 
        "some-section-description": "Some other description"
    } 
}

Example of a setup

Given that we want to have support for the languages English and Spanish, a setup could look like this.

The folder structure

| .
|--- src
|   |--- <your source code>
|--- messages
|   |--- config.json
|   |--- en.json
|   |--- es.json
| package.json
| ...

config.json

{
    "default": "en",
    "languages": [
        {
            "code": "en",
            "name": "English"
        },
        {
            "code": "es",
            "name": "Spanish"
        }
    ]
}

en.json

{
    "home": {
        "welcome": "Welcome message",
        "about": "Some description"
    },
    "metadata": {
        "home-title": "Some title for the home page",
        "home-description": "Some description for the home page"
    }
}

es.json

{
    "home": {
        "welcome": "Welcome message in spanish",
        "about": "Some description in spanish"
    },
    "metadata": {
        "home-title": "Some title for the home page in spanish",
        "home-description": "Some description for the home page in spanish"
    }
}

Set up wrapper

In order for using the language files you've just created and make their contents available in all of your sub-modules, you need to initialize a wrapper in your layout.tsx file.

import './globals.css'
// Import the wrapper and the Configuration class
import { LocalizerWrapper, Configuration } from 'nextjs-static-page-localizer'

// Load the configuration
const config = require('@/messages/config')

// Set up the default title and description
export const metadata = {
  title: 'Default Title',
  description: 'Default description',
}

export default async function RootLayout({
  children,
  params
}: {
  children: React.ReactNode,
  params: any
}) {

  // Create the configuration object based on the loaded configuration
  const configuration = new Configuration(config.default, config.languages, config.messages)

  // Wrap the main section with the wrapper and pass in the configuration
  return (
    <html>
      <body>
        <LocalizerWrapper configuration={configuration}>
          <main>
            {children}
          </main>
        </LocalizerWrapper>
      </body>
    </html>
  )
}

For this we created an additional file in the messages folder to keep the code at the layout element cleaner, config.js, which loads the data from the files fo us. You could do the same or load the data in a similar manner directly to your layout element.

const config = require('./config.json');

const en = require('./en.json');
const no = require('./no.json');
const cs = require('./cs.json');

const messages = {
    "en": en,
    "no": no,
    "cs": cs
}

module.exports = {
    default: config.default,
    languages: config.languages,
    messages: messages
}

Using the content in components

So far we've talked about how to create the structure. Now we will talk about how to use the content in our app.

As you might have noticed all the content is seperated in sections. This is to make it more easily organized and to create some logic to seperate different pages in your app.

The component makes use of the query parameter lang to decide what language it should use. If this is not set it uses the default language that is specified.

// Neccesary
"use client";

import React, { useState } from "react";
// Import translations fetcher
import { useTranslationsFetcher } from "nextjs-static-page-localizer";

function YourComponent(){
    // Fetch translations
    const translations = useTranslationsFetcher();
    // Select a section by name
    const home_section = translations("home");

    // Use the section to get each element by the specified key
    return (
        <div>
            <h1>{home_section("title")}</h1>
            <p>{home_section("description")}</p>
        </div>
    )
}

export default YourComponent

Using HTML language setter

This package also support setting the lang section of the root HTML element. We will now add this to the code we made previously. This is quite easy to do, and it will specify the language as of the ?lang=<code> section of the url. If it does not find this, it will specify the default language as the language of the page.

"use client";

import React, { useState } from "react";
// Add the language setter to the imports
import { useTranslationsFetcher, useLanguageSetter } from "nextjs-static-page-localizer";
function YourComponent(){
    const translations = useTranslationsFetcher();

    // Use the language setter
    useLanguageSetter();

    const home_section = translations("home");

    return (
        <div>
            <h1>{home_section("title")}</h1>
            <p>{home_section("description")}</p>
        </div>
    )
}

export default YourComponent

Specifying page metadata

In order to make even the title and description localized we can use the metadata setter to set the content of the header title and description as we have specified in our language files.

"use client";

import React, { useState } from "react";
// Add the metadata setter to the imports
import { useTranslationsFetcher, useLanguageSetter, useMetadataSetter } from "nextjs-static-page-localizer";
function YourComponent(){
    const translations = useTranslationsFetcher();

    useLanguageSetter();
    // Use the metadata setter by specifying the sections it should use
    useMetadataSetter("home-title", "home-description");

    const home_section = translations("home");

    return (
        <div>
            <h1>{home_section("title")}</h1>
            <p>{home_section("description")}</p>
        </div>
    )
}

export default YourComponent

Create a Link to other sub-pages

In your project you probably wither have, or will at some point need to have some sub-pages. When you have that you'll need some way to navigate between the pages. Given that we are using a query parameter for determining the prefered language this needs to be part of the link as your're going from one sub-page to another without loosing the setting.

We have for this purpose created a link element that builds on the NEXT.js Link element, which handles this language setting for you. Under is an example of how that can be set up.

'use client'
// Import the translationsfetcher
import { useTranslationsFetcher } from "nextjs-static-page-localizer";
// Import the LocalizedLink component
import { LocalizedLink } from "nextjs-static-page-localizer/components";

export default function Header() {
    // Import the translations so that the links can have localized Labels as well
    const tranlations = useTranslationsFetcher();
    // Get the section in which you have the link names (not neccesarily the same as this)
    const link_names = tranlations("links");
    
    // Create the link elements 
    return (
        <header>
            <div className="menu">
                <LocalizedLink href="/">link_names("home")</LocalizedLink>
                <LocalizedLink href="/about">link_names("about")</LocalizedLink>
            </div>
        </header>
    );
}

Create a Language Switcher

Now we'll also have to have a way to set the language so that the user can switch the language the page is in. We have also created a component that switches the languages while not changing the page that one currently is on. We will now expand on the last example to add the language setters. Here we'll do it dynamically based on the languages we have in our config, however you can create each component by it self if you wish to do so.

'use client'
// Import the language interface
import { Language } from "nextjs-static-page-localizer/interfaces";
// Import the useLocalization
import { useTranslationsFetcher, useLocalization } from "nextjs-static-page-localizer";
// Import the LanguageSwitcher component
import { LocalizedLink, LanguageSwitcher } from "nextjs-static-page-localizer/components";

export default function Header() {
    // Fetch the configuration
    const { configuration } = useLocalization();
    const tranlations = useTranslationsFetcher();
    const link_names = tranlations("links");
    
    // Create a component for each language dynamically based on the languages 
    return (
        <header>
            <div className="languages">
                {
                    configuration.languages.map((language:Language) => {
                        return (
                            <LanguageSwitcher
                                key={language.code}
                                lang={language.code}
                                >
                                <h4>{language.name}</h4>
                            </LanguageSwitcher>
                        );
                    })
                }
            </div>
            <div className="menu">
                <LocalizedLink href="/"><h2>link_names("home")</h2></LocalizedLink>
                <LocalizedLink href="/about"><h2>link_names("about")</h2></LocalizedLink>
            </div>
        </header>
    );
}
1.1.1

7 months ago

1.0.19

8 months ago

1.1.0

8 months ago

1.0.18

8 months ago

1.0.17

8 months ago

1.0.16

8 months ago

1.0.22

8 months ago

1.0.21

8 months ago

1.0.20

8 months ago

1.0.11

8 months ago

1.0.15

8 months ago

1.0.14

8 months ago

1.0.13

8 months ago

1.0.12

8 months ago

1.0.10

8 months ago

1.0.9

8 months ago

1.0.8

8 months ago

1.0.7

8 months ago

1.0.6

8 months ago

1.0.5

8 months ago

1.0.4

8 months ago

1.0.3

8 months ago

1.0.2

8 months ago

1.0.1

8 months ago

1.0.0

8 months ago