Skip to content

Commit

Permalink
Add an example which uses next-18next without custom server.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixmosh committed Aug 21, 2020
1 parent 9325398 commit fc8525f
Show file tree
Hide file tree
Showing 19 changed files with 6,404 additions and 0 deletions.
14 changes: 14 additions & 0 deletions examples/next-with-next-i18next-without-custom-server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Dependencies
node_modules

# Dist
dist

# OS
.DS_Store

# Development Environment
.vscode

# Logs
runtime.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Simple example: next-i18next

## What is this?

This subdirectory is a simple example of how to use [next-i18next](https://github.com/isaachinman/next-i18next) with [NextJs](https://github.com/zeit/next.js) to get translations up and running quickly and easily, while fully supporting SSR, multiple namespaces with codesplitting, etc.

## For more info...

You may have arrived here from the [NextJs](https://github.com/zeit/next.js) repository, or the [react-i18next](https://github.com/i18next/react-i18next/) repository. Either way, for more documentation, please visit the [main README](https://github.com/isaachinman/next-i18next).
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import PropTypes from 'prop-types'
import { version } from 'next-i18next/package.json'
import { withTranslation } from '../i18n'

const Footer = ({ t }) => (
<footer>
<p>
{t('description')}
</p>
<p>
next-i18next v
{version}
</p>
</footer>
)

Footer.propTypes = {
t: PropTypes.func.isRequired,
}

export default withTranslation('footer')(Footer)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import PropTypes from 'prop-types'
import Head from 'next/head'

const Header = ({ title }) => (
<>
<Head>
<title>next-i18next</title>

<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />
<link href="/static/app.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/typicons/2.0.9/typicons.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400|Oswald:600" rel="stylesheet" />
<link data-react-helmet="true" rel="icon" href="https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/spaces%2F-L9iS6Wm2hynS5H9Gj7j%2Favatar.png?generation=1523462254548780&amp;alt=media" />
</Head>
<h2>
next-i18next
<hr />
</h2>
<h1>
{title}
</h1>
<a
className="github"
href="//github.com/isaachinman/next-i18next"
>
<i className="typcn typcn-social-github-circular" />
</a>
</>
)

Header.propTypes = {
title: PropTypes.string.isRequired,
}

export default Header
22 changes: 22 additions & 0 deletions examples/next-with-next-i18next-without-custom-server/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const NextI18Next = require('next-i18next').default
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig
const path = require('path')


const nextI18Next = new NextI18Next({
otherLanguages: ['de'],
localeSubpaths,
localePath: path.resolve('./public/static/locales')
});

if (process.env.NODE_ENV !== 'production') {
if(process.browser) {
const { applyClientHMR } = require('i18next-hmr/client');
applyClientHMR(nextI18Next.i18n);
} else {
const { applyServerHMR } = require('i18next-hmr/server');
applyServerHMR(nextI18Next.i18n);
}
}

module.exports = nextI18Next
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { nextI18NextRewrites } = require('next-i18next/rewrites');
const path = require('path');
const localeSubpaths = {};

module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
webpack(config, options) {
if (!options.isServer && config.mode === 'development') {
const { I18NextHMRPlugin } = require('i18next-hmr/plugin');
config.plugins.push(
new I18NextHMRPlugin({
localesDir: path.resolve(__dirname, 'public/static/locales')
})
);
}

return config;
}
};
24 changes: 24 additions & 0 deletions examples/next-with-next-i18next-without-custom-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "-",
"version": "1.0.0",
"main": "./dist/index.js",
"license": "MIT",
"engines": {
"node": ">=8"
},
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start -p ${PORT:=3000}"
},
"devDependencies": {
"i18next-hmr": "^1.5.6"
},
"dependencies": {
"i18next": "^14.0.1",
"next": "^9.5.0",
"next-i18next": "6.0.2",
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import App from 'next/app'
import { appWithTranslation } from '../i18n'

const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />

MyApp.getInitialProps = async (appContext) => ({ ...await App.getInitialProps(appContext) })

export default appWithTranslation(MyApp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import PropTypes from 'prop-types'
import { withTranslation } from '../i18n'

const Error = ({ statusCode, t }) => (
<p>
{statusCode
? t('error-with-status', { statusCode })
: t('error-without-status')}
</p>
)

Error.getInitialProps = async ({ res, err }) => {
let statusCode = null
if (res) {
({ statusCode } = res)
} else if (err) {
({ statusCode } = err)
}
return {
namespacesRequired: ['common'],
statusCode,
}
}

Error.defaultProps = {
statusCode: null,
}

Error.propTypes = {
statusCode: PropTypes.number,
t: PropTypes.func.isRequired,
}

export default withTranslation('common')(Error)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import PropTypes from 'prop-types'
import { i18n, Link, withTranslation } from '../i18n'
import Header from '../components/Header'
import Footer from '../components/Footer'

const Homepage = ({ t }) => (
<>
<main>
<Header title={t('h1')} />
<div>
<button
type='button'
onClick={() => i18n.changeLanguage(i18n.language === 'en' ? 'de' : 'en')}
>
{t('change-locale')}
</button>
<Link href='/second-page'>
<button
type='button'
>
{t('to-second-page')}
</button>
</Link>
</div>
</main>
<Footer />
</>
)

Homepage.getInitialProps = async () => ({
namespacesRequired: ['common', 'footer'],
})

Homepage.propTypes = {
t: PropTypes.func.isRequired,
}

export default withTranslation('common')(Homepage)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import PropTypes from 'prop-types'
import { withTranslation, Link } from '../i18n'
import Header from '../components/Header'
import Footer from '../components/Footer'

const SecondPage = ({ t }) => (
<>
<main>
<Header title={t('h1')} />
<Link href='/'>
<button
type='button'
>
{t('back-to-home')}
</button>
</Link>
</main>
<Footer />
</>
)

SecondPage.getInitialProps = async () => ({
namespacesRequired: ['second-page', 'footer'],
})

SecondPage.propTypes = {
t: PropTypes.func.isRequired,
}

export default withTranslation('second-page')(SecondPage)
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#__next {
font-family: 'Open Sans', sans-serif;
text-align: center;
background-image: linear-gradient(to left top, #ffffff, #f5f5f5, #eaeaea, #e0e0e0, #d6d6d6);
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vw;
}

h1,
h2 {
font-family: 'Oswald', sans-serif;
}

h1 {
font-size: 3rem;
margin: 5rem 0;
}
h2 {
min-width: 18rem;
font-size: 2rem;
opacity: 0.3;
}

p {
line-height: 1.65em;
}
p:nth-child(2) {
font-style: italic;
opacity: 0.65;
margin-top: 1rem;
}

a.github {
position: fixed;
top: 0.5rem;
right: 0.75rem;
font-size: 4rem;
color: #888;
opacity: 0.8;
}
a.github:hover {
opacity: 1;
}

button {
display: inline-block;
vertical-align: bottom;
outline: 0;
text-decoration: none;
cursor: pointer;
padding: .4rem;
background-color: rgba(255, 255, 255, 0.5);
box-sizing: border-box;
font-size: 1em;
font-family: inherit;
border-radius: 3px;
margin: .1rem;
transition: box-shadow .2s ease;
user-select: none;
line-height: 2.5em;
min-height: 40px;
padding: 0 .8em;
border: 0;
color: inherit;
position: relative;
transform: translateZ(0);
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .26);
margin: 0.8rem;
}

button:hover,
button:focus {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, .4);
}

main {
display: flex;
flex-direction: column;
flex: 1;
justify-content: center;
align-items: center;
}
footer {
background-color: rgba(255, 255, 255, 0.5);
width: 100vw;
padding: 3rem 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"h1": "Ein einfaches Beispiel",
"change-locale": "Wechseln Locale",
"to-second-page": "Zur zweiten Seite",
"error-with-status": "Auf dem Server ist ein Fehler ({{statusCode}}) aufgetreten",
"error-without-status": "Auf dem Server ist ein Fehler aufgetreten"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"description": "Dies ist eine Nicht-Seitenkomponente, die einen eigenen Namespace erfordert"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"h1": "Eine zweite Seite, um das Routing zu demonstrieren",
"back-to-home": "Zurück zur Hauptseite"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"h1": "A simple example",
"change-locale": "Change locale",
"to-second-page": "To second page",
"error-with-status": "A {{statusCode}} error occurred on server",
"error-without-status": "An error occurred on the server"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"description": "This is a non-page component that requires its own namespace"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"h1": "A second page, to demonstrate routing",
"back-to-home": "Back to home"
}
Loading

0 comments on commit fc8525f

Please sign in to comment.