Coder Social home page Coder Social logo

epic-language's Introduction

epic-language

Language Logo

AI-assisted translation library for React and React Native.

  • 3 ways to store translations
    • Bundled Generated manually or with AI during build and stored in the bundle
    • CDN Generated with AI during build time and stored in a Serverless function
    • Serverless Translated with AI and cached during runtime in a Serverless function
  • Support for React Native
  • <Text id="myTranslationKey" /> component to render translations
  • Replacements with {} or {1} {2} in translations
  • Translations generated on demand using LLMs (AI)
  • Optimized for development phase: no need to commit any translations to source!

This project was built to try the Bun 🐰 runtime, Cursor AI 🖱️ editor and CodeWhisperer 🤫. See this blog post detailing my experiences.

Usage with Buildtime Translation

This is the most basic method where all translations are bundled into the main JavaScript bundle. This is useful for development, when supporting only few languages or when distributing as a package like React Native apps. To use this method, create a main JSON file in the default language containing the initial translations. The CLI translation script can then be used to translate these keys during installation or the build. Running this will require OPENAI_API_KEY and OPENAI_ORGANIZATION (optional) environment variables to be present. When using Bun with bunx instead of npx these variables will automatically be loaded from your .env file.

npx epic-language --input translations.json --output translations --language en --languages es,zh

Once generated the translation files can be imported as JSON and bundled directly into JavaScript.

import { create, Language } from 'epic-language'
import spanishSheet from './translations/es.json'
import chineseSheet from './translations/zh.json'

const { translate } = create({
  // Initial translations in default language.
  translations: {
    title: 'My Title',
    replacement: 'Counter: {}',
    multipleOrderedReplacements: "What's {2} current {1}?",
  },
  // Additional translated language sheets.
  sheets: {
    [Language.es]: spanishSheet,
    [Language.zh]: chineseSheet,
  },
})

translate('title') // My Title
translate('replacement', 5) // Counter: 5
translate('multipleOrderedReplacements', ['pastime', 'your']) // What's your current pastime?

Individual Translations Served As Static Files

To avoid bundling translations with your regular JavaScript code and only send the required translations to the user you can configure a static route. In most build tools assets from the /public folder will be served statically.

npx epic-language --input translations.json --output public/translation --language en --languages es,zh
import { create, Language } from 'epic-language'
// Always load the translations for the default language.
import translations from './translations.json'

const { translate } = create({
  // Initial translations in default language.
  translations,
  // Translation files served statically as JSON files per language.
  // [language] will be replaced with the language (en, es, zh etc.)
  route: 'translation/[language].json',
})

translate('title') // My Title

Usage with Runtime Translation and Caching

The route can point to a Serverless or Edge API function that will generate and cache the desired translations. This avoids translating every language during the build and will save a lot of time during the development phase, while ensuring translations always work.

import { create } from 'epic-language'
import translations from './translations.json'

const { translate } = create({
  // Initial translations in default language.
  translations,
  // Route to load translations for user language.
  // [language] will be replaced with the language (en, es, zh etc.)
  route: '/api/translation/[language]',
})

translate('title') // My Title
translate('counter', '5') // Counter: 5

The following functions have been tested on Vercel and can be adapted accordingly for other hosting providers. It's important to make sure the OPENAI_API_KEY and OPENAI_ORGANIZATION (optional) environment variables are available in your functions. Check out the /api source code of the demo application.

Serverless Function

import { readFileSync } from 'fs'
import { it } from 'avait'
import { Language } from 'epic-language'
import { translate } from 'epic-language/function'
import type { VercelRequest, VercelResponse } from '@vercel/node'

export default async function handler(request: VercelRequest, response: VercelResponse) {
  const language = request.query.lang as Language
  if (!(language in Language))
    return response.status(500).json({ error: `Missing language "${language}"` })
  const englishSheet = JSON.parse(
    readFileSync(new URL('../../translations.json', import.meta.url), 'utf8'),
  )
  const { error, value: sheet } = await it(translate(JSON.stringify(englishSheet), language))
  if (error)
    return response.status(500).json({ error: `Translation for language "${language}" failed!` })
  response.status(200).json(sheet)
}

Edge Function

import { it } from 'avait'
import { Language } from 'epic-language'
import { translate } from 'epic-language/function'
import translations from '../../translations.json'

export const runtime = 'edge'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const language = searchParams.get('lang') as Language
  if (!(language in Language)) return new Response(`Missing language "${language}"`)
  const { error, value: sheet } = await it(translate(JSON.stringify(translations), language))
  if (error) return new Response(`Translation for language "${language}" failed!`)
  return Response.json(sheet)
}

Usage with React Native

import { create, Language } from 'epic-language/native'

const { translate, Text } = create(
  // Default translations.
  { title: 'My App' },
  // Translations in additional languages.
  {
    [Language.es]: { title: 'Mi aplicación' },
    [Language.zh]: { title: '我的應用程式' },
  },
  // Language, defaults to english.
  Language.en,
)

const settingsText = translate('title')
const Heading = <Text style={{ fontSize: 32 }}>title</Text>

ES Module exports are still an experimental feature in React Native's Metro bundler. Since this plugin requires them you have to turn them in your metro.config.js with:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')

const config = {
  resolver: {
    unstable_enablePackageExports: true,
  },
}

module.exports = mergeConfig(getDefaultConfig(__dirname), config)

Advanced Usage

The State object allows you to keep track of the status for loading language sheets.

import { create, State } from 'epic-language'

const { translate } = create({ translations: { title: 'My Title' } })

State.current === 'ready' // Current state: initial, loading or ready.
State.listen((state, language) => console.log(state, language)) // Listen to state changes.
State.languages // List of all available translated languages.

It's also possible to insert JSX.Element as replacements.

import { create } from 'epic-language'

const { translate } = create({ translations: { counter: 'Count {} at {}' } })

translate(counter, [<span>5</span>, <div style={{ color: 'red' }}>{`12:34 PM`}</div>]) // Count <span>5</span> at <div>12:34 PM</div>

epic-language's People

Contributors

tobua avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.