A fully type-safe and lightweight internationalization library for all your TypeScript and JavaScript projects.

Overview

🌍 typesafe-i18n

A fully type-safe and lightweight internationalization library for all your TypeScript and JavaScript projects.

npm version GitHub Top Language bundle size types included bump version & publish to npm Generic badge Sponsor this project

Advantages

🐤 lightweight (~1kb)
👌 easy to use syntax
🏃 fast and efficient
🦺 prevents you from making mistakes (also in plain JavaScript projects)
👷 creates boilerplate code for you
💬 supports plural rules
📅 allows formatting of values e.g. locale-dependent date or number formats
↔️ supports switch-case statements e.g. for gender-specific output
⬇️ option for asynchronous loading of locales
📚 supports multiple namespaces
⏱️ supports SSR (Server-Side Rendering)
🤝 can be used for frontend, backend and API projects
🔍 locale-detection for browser and server environments
🔄 import and export translations from/to files or services
no external dependencies

Interactive Live Demo

Click here to see an interactive demo of typesafe-i18n showing some key aspects of the type-checking capabilities of this internationalization library.

Works with

Table of Contents

  • Get started - how to add typesafe-i18n to your project
  • Usage - how to implement different use-cases
  • Typesafety - how to get the best typesafety features
  • Syntax - how to use the translation functions
  • Dictionary - how to structure your translations
  • Namespaces - how to optimize loading of your translations
  • Formatters - how to format dates and numbers
  • Switch-Case - how to output different words depending on an argument
  • Locale-detection - how to detect an user's locale
  • Integrations - how to integrate other i18n services
  • Sizes - how much does typesafe-i18n add to your bundle size
  • Performance - how efficient is typesafe-i18n implemented
  • Sponsors - how to help this project grow
  • FAQs - how to get your questions answered

Get started

  1. ⌨️ Run the setup process and automatically detect the config needed

    npx typesafe-i18n --setup-auto

    or manually configure typesafe-i18n by answering a few questions

    npx typesafe-i18n --setup

    It didn't work? See here for possible troubleshooting.

  2. 👀 Take a look at the generated files and it's folder-structure

  3. 📖 Explore the assets

    typesafe-i18n offers a lot. Just press cmd + F to search on this page or see the table of contents that will link you to more specific subpages with more details.

  4. Star this project on GitHub

    Thanks! This helps the project to grow.


Having trouble setting up typesafe-i18n? Reach out to us via Github Discussions or on Discord.

manual installation

npm install typesafe-i18n

changelog

The changelog of this project can be found here

migrations

Long-term goals

Curious about what comes next? See this discussion to learn more about the plans for the future of this project.

Contributions

If you would like to get involved within this project, take a look at this discussion.

Usage

The package can be used inside JavaScript and TypeScript applications. You will get a lot of benefits by running the generator since it will create a few wrappers to provide you with full typesafety.

You can use typesafe-i18n in a variety of project-setups:

Other frameworks

All you need is inside the generated file i18n-utils.ts. You can use the functions in there to create a small wrapper for your application.

Feel free to open a new discussion if you need a guide for a specific framework.

Custom usage

See here if you want to learn how you can use typesafe-i18n to implement your own specific use-case.

Browser Support

The library should work in all modern browsers. It uses some functionality from the Intl namespace. You can see the list of supported browsers here. If you want to support older browsers that don't include these functions, you would need to include a polyfill like intl-pluralrules.

Typesafety

Here you can see some examples where typesafe-i18n can help you:

typesafe auto-completion for all your defined locales

typesafe locales completion

typesafe auto-completion for all available translations

typesafe translation key completion

you will get an error if you forget to pass arguments

typesafe number of arguments

you will get an error if you pass the wrong type arguments

typesafe arguments 1 typesafe arguments 2

you will get an error if you forgot to add a translation in a locale

typesafe keys in translations

you will get an error when a translation is missing an argument

typesafe arguments in translation

The typesafe-i18n package allows us to be 100% typesafe for our translation functions and even the translations for other locales itself. The generator outputs TypeScript definitions based on your base locale.

You will also benefit from full typesafe JavaScript code via JSDoc-annotations.

Integration with other services

typesafe-i18n comes with an API that allows other services to read and update translations. You can connect ot other services by using the importer and exporter functionality:

Sizes

The footprint of the typesafe-i18n package is smaller compared to other existing i18n packages. Most of the magic happens in development mode, where the generator creates TypeScript definitions for your translations. This means, you don't have to ship the whole package to your users. The only two parts, that are needed in production are:

  • string-parser: detects variables, formatters and plural-rules in your localized strings
  • translation function: injects arguments, formats them and finds the correct plural form for the given arguments

These parts are bundled into the core functions. The sizes of the core functionalities are:

Apart from that there can be a small overhead depending on which utilities and wrappers you use.

There also exists a useful wrapper for some frameworks:

Performance

The package was optimized for performance:

  • the amount of network traffic is kept small
    The translation functions are small. Only the locales that are used are loaded
  • no unnecessary workload
    Parsing your translation file for variables and formatters will only be performed when you access a translation for the first time. The result of that parsing process will be stored in an optimized object and kept in memory.
  • fast translations
    Passing variables to the translation function will be fast, because its treated like a simple string concatenation. For formatting values, a single function is called per formatter.

If you use typesafe-i18n you will get a smaller bundle compared to other i18n solutions. But that doesn't mean, we should stop there. There are some possible optimizations planned to decrease the bundle size even further.

Sponsors

Become a sponsor ❤️ if you want to support my open source contributions.

ivanhofer's sponsors

Thanks for sponsoring my open source work!

FAQs


Dou you still have some questions? Reach out to us via Github Discussions or on Discord.


Installing typesafe-i18n fails

Running the npx command with a npm version <7.0.0 will probably fail because it will not include peerDependencies.

You could try installing it locally via:

npm install typesafe-i18n

and then run the setup-command from within the node_modules folder via:

./node_modules/typesafe-i18n/cli/typesafe-i18n.mjs --setup-auto

here is the original issue with some additional information: #142


I added a new translation to my locale file, but TypeScript gives me the Error Property 'XYZ' does not exist on type 'TranslationFunctions'

Make sure to run the generator after you make changes to your base translation file. The generator will generate and update the types for you.


I don't use TypeScript, can I also use typesafe-i18n inside JavaScript applications?

Yes, you can. See the usage section for instructions. Even if you don't use TypeScript you can still improve from some typesafety features via JSDoc-annotations.


I added a new translation to my locale file, but the generator will not create new types

The generator will only look for changes in your base locale file. Make sure to always update your base locale file first, in order to get the correct auto-generated types. If you want to change your base locale file, make sure to give it the type of BaseTranslation. All other locales should have the type of Translation. E.g. if you set your base locale to italian, you would need to do it like this:

  • set your base locale to italian (it) in ´.typesafe-i18n.json`:

    {
       "baseLocale": "it"
    }
  • define the type of your base locale as BaseTranslation

    // file 'src/i18n/it/index.ts'
    import type { BaseTranslation } from '../i18n-types'
    
    const it: BaseTranslation = {
       WELCOME: "Benvenuto!"
    }
    
    export default it
  • define the type of your other locales as Translation

    // file 'src/i18n/en/index.ts'
    import type { Translation } from '../i18n-types'
    
    const en: Translation = {
       WELCOME: "Welcome!"
    }
    
    export default en

The generator keeps overriding my changes I make to the i18n-files

The generator creates some helpful wrappers for you. If you want to write your own wrappers, you can disable the generation of these files by setting the generateOnlyTypes option to true.


Is typesafe-i18n supported by i18n-ally?

Yes, you can configure i18n-ally like this. There is currently also an open PR that will add official support for typesafe-i18n.


How can I access a translation dynamically?

When you want to dynamically access a translation, you can use the usual JavaScript syntax to access a property via a variable (myObject[myVariable]).

  1. define your translations
// i18n/en.ts
import type { BaseTranslation } from '../i18n-types'

const en: BaseTranslation = {
   category: {
      simple: {
         title: 'Simple title',
         description: 'I am a description for the "simple" category',
      },
      advanced: {
         title: 'Advanced title',
         description: 'I am a description for the "advanced" category',
      }
   }
}

export default en
  1. use it in your components
<script lang="ts">
   // Component.svelte

   import LL from '$i18n/i18n-svelte'
   import type { Translation } from '$i18n/i18n-types'

   // ! do not type it as `string`
   // by restricting the type, you don't loose the typesafety features
   export let category: keyof Translation['category'] = 'simple'
</script>

<h2>{$LL.category[category].title()}

<p>
   {$LL.category[category].description()}
<p>

How do I render a component inside a Translation?

By default typesafe-i18n at this time does not provide such a functionality. But you could easily write a function like this:

import { LocalizedString } from 'typesafe-i18n'

// create a component that handles the translated message

interface WrapTranslationPropsType {
   message: LocalizedString,
   renderComponent: (messagePart: LocalizedString) => JSX.Element
}

export function WrapTranslation({ message, renderComponent }: WrapTranslationPropsType) {
   // define a split character, in this case '<>'
   let [prefix, infix, postfix] = message.split('<>') as LocalizedString[]

   // render infix only if the message doesn't have any split characters
   if (!infix && !postfix) {
      infix = prefix
      prefix = '' as LocalizedString
   }

   return <>
      {prefix}
      {renderComponent(infix)}
      {prefix}
   </>
}

// your translations would look something like this

const en = {
   'WELCOME': 'Hi {name:string}, click <>here<> to create your first project'
   'LOGOUT': 'Logout'
}

export default en


// create a wrapper for a component for easier usage

interface WrappedButtonPropsType {
   message: LocalizedString,
   onClick: () => void,
}

export function WrappedButton({ message, onClick }: WrappedButtonPropsType) {
   return <WrapTranslation
      message={message}
      renderComponent={(infix) => <button onClick={onClick}>{infix}</button>} />
}

// use it inside your application

export function App() {
   return <>
      <header>
         <WrappedButton message={LL.LOGOUT()} onClick={() => alert('do logout')}>
      </header>
      <main>
         <WrappedButton message={LL.WELCOME({ name: 'John' })} onClick={() => alert('clicked')}>
      </main>
   <>
}

This is an example written for a react application, but this concept can be used with any kind of framework.

Basically you will need to write a function that splits the translated message and renders a component between the parts. You can define your split characters yourself but you would always need to make sure you add them in any translation since typesafe-i18n doesn't provide any typesafety for these characters (yet).


I have two similar locales (only a few translations are different) but I don't want to duplicate my translations

Your locale translation files can be any kind of JavaScript object. So you can make object-transformations inside your translation file. The only restriction is: in the end it has to contain a default export with type Translation. You could do something like this:

  • create your BaseTranslation

    // file 'src/i18n/en/index.ts'
    import type { BaseTranslation } from '../i18n-types'
    
    const en: BaseTranslation = {
       WELCOME: "Welcome to XYZ",
       // ... some other translations
    
       COLOR: "colour"
    }
    
    export default en
  • create your other translation that overrides specific translations

    // file 'src/i18n/en-US/index.ts'
    import type { Translation } from '../i18n-types'
    import en from '../en' // import translations from 'en' locale
    
    const en_US: Translation = {
       ...en, // use destructuring to copy all translations from your 'en' locale
    
       COLOR: "color" // override specific translations
    }
    
    export default en_US

    If you are using nested translations, you probably need a function like lodash/merge to make a deep merge of your translations.

    import { merge } from 'lodash'
    
    const en_US: Translation = deepMerge(en, {
       labels: {
          color: "color" // override specific translations
       }
    })
    
    export default en_US

For certain locales I don't want to output a variable, but due to the strict typing I have to specify it in my translation

The generated types are really strict. It helps you from making unintentional mistakes. If you want to opt-out for certain translations, you can use the any keyword.

  • create your BaseTranslation with a translation containing a parameter

    // file 'src/i18n/en/index.ts'
    import type { BaseTranslation } from '../i18n-types'
    
    const en: BaseTranslation = {
       HELLO: "Hi {name}!",
    }
    
    export default en
  • create another locale without that parameter by disabling the strict type checking with as any

    // file 'src/i18n/de/index.ts'
    import type { Translation } from '../i18n-types'
    
    const de: Translation = {
       HELLO: "Hallo!" as any // we don't want to output the 'name' variable
    }
    
    export default de

WARNING! the usage of 'any' can introduce unintentional mistakes in future. It should only be used when really necessary and you know what you are doing.

A better approach would be to create a custom formatter e.g.

  • create your translation and add a formatter to your variable

    // file 'src/i18n/en/index.ts'
    import type { BaseTranslation } from '../i18n-types'
    
    const en: BaseTranslation = {
       HELLO: "Hi {name|nameFormatter}!",
    }
    
    export default en
    // file 'src/i18n/de/index.ts'
    import type { Translation } from '../i18n-types'
    
    const de: Translation = {
       HELLO: "Hallo {name|nameFormatter}!"
    }
    
    export default de
  • create the formatter based on the locale

    // file 'src/i18n/formatters.ts'
    import type { FormattersInitializer } from 'typesafe-i18n'
    import type { Locales, Formatters } from './i18n-types'
    import { identity, ignore } from 'typesafe-i18n/formatters'
    
    export const initFormatters: FormattersInitializer<Locales, Formatters> = (locale: Locales)    => {
    
       const nameFormatter =
          locale === 'de'
             // return an empty string for locale 'de'
             ? ignore // same as: () => ''
             // return the unmodified parameter
             : identity // same as: (value) => value
    
       const formatters: Formatters = {
          nameFormatter: nameFormatter
       }
    
       return formatters
    }

Why does the translation function return a type of LocalizedString and not the type string itself?

With the help of LocalizedString you could enforce texts in your application to be translated. Lets take an Error message as example:

const showErrorMessage(message: string) => alert(message)

const createUser = (name: string, password: string) => {
   if (name.length === 0) {
      showErrorMessage(LL.user.create.nameNotProvided())
      return
   }

   if (isStrongPassword(password)) {
      showErrorMessage('Password is to weak')
      return
   }

   // ... create user in DB
}

In this example we can pass in any string, so it can also happen that some parts of your application are not translated. To improve your i18n experience a bit we can take advantage of the LocalizedString type:

import type { LocalizedString } from 'typesafe-i18n'

const showErrorMessage(message: LocalizedString) => alert(message)

const createUser = (name: string, password: string) => {
   if (name.length === 0) {
      showErrorMessage(LL.user.create.nameNotProvided())
      return
   }

   if (isStrongPassword(password)) {
      showErrorMessage('Password is to weak') // => ERROR: Argument of type 'string' is not assignable to parameter of type 'LocalizedString'.
      return
   }

   // ... create user in DB
}

With the type LocalizedString you can restrict your functions to only translated strings.


Tests are not running with Jest

Unfortunately there are some open issues in the Jest repository regarding modern package export formats so jest doesn't know where to load files from.

You need to manually tell jest where these files should be loaded from, by defining moduleNameMapper inside your jest.config.js:

// jest.config.js
module.exports = {
   moduleNameMapper: {
      "typesafe-i18n/angular": "typesafe-i18n/angular/index.cjs",
      "typesafe-i18n/react": "typesafe-i18n/react/index.cjs",
      "typesafe-i18n/solid": "typesafe-i18n/solid/index.cjs",
      "typesafe-i18n/svelte": "typesafe-i18n/svelte/index.cjs",
      "typesafe-i18n/vue": "typesafe-i18n/vue/index.cjs",
      "typesafe-i18n/formatters": "typesafe-i18n/formatters/index.cjs",
      "typesafe-i18n/detectors": "typesafe-i18n/detectors/index.cjs",
   }
};

here is the original issue with some additional information: #140


With Node.JS the Intl package does not work with locales other than 'en'

Node.JS, by default, does not come with the full intl support. To reduce the size of the node installment it will only include 'en' as locale. You would need to add it yourself. The easiest way is to install the intl package

> npm install intl

and then add following lines on top of your src/i18n/formatters.ts file:

const intl = require('intl')
intl.__disableRegExpRestore()
globalThis.Intl.DateTimeFormat = intl.DateTimeFormat

Then you should be able to use formatters from the Intl namespace with all locales.

Comments
  • Error: Cannot find module 'typesafe-i18n/formatters'

    Error: Cannot find module 'typesafe-i18n/formatters'

    Now the error appears in developer mode.

    yarn dev Error when evaluating SSR module /src/i18n/formatters.ts: Error: Cannot find module 'typesafe-i18n/formatters' from 'D:/app/src/i18n'

    "typesafe-i18n": "^2.36.0" "@sveltejs/kit": "^1.0.0-next.138",

    bug help wanted 
    opened by nn1k4 13
  • The 2.49.0 version and 2.54.0 are critical incompatible. (silent shutdown..?)

    The 2.49.0 version and 2.54.0 are critical incompatible. (silent shutdown..?)

    Describe the bug

    Many projects that installed this project lightly as npm i typesafe-i18n in version 2.49.0 are currently not working. So I'm using the version of typesafe-i18n by lowering it to 2.49.0 version.

    Can you check this out? I think this is fatal.

    Reproduction

    Initialize empty project of polyger (it based typesafe-i18n 2.49.0)

    mkdir some_test
    cd some_test
    npm init -y
    npm install [email protected]
    npx polyger
    

    The above command will be nothing executed and silently shutdown. (because some weird silent problem has been occoured in typesafe-i18n.)

    then I'll install the previous version of typesafe-i18n and install it.

    npm i [email protected]
    npx polyger
    

    and this one is working and showing some initialize messages. (if you can confirm it, just you can ctrl+c or command + c to shut it dowm.)

    By executing the command below, you can check the previous version as it is.

    npm i [email protected]
    npx polyger
    

    you can now seeing nothing to executed and can be confirm silent shutdown.

    Logs

    No response

    Config

    No response

    Additional information

    No response

    bug 
    opened by hmmhmmhm 12
  • Cannot find package 'typescript' imported

    Cannot find package 'typescript' imported

    Describe the bug

    npx: installed 1 in 1.144s
    internal/process/esm_loader.js:74
        internalBinding('errors').triggerUncaughtException(
                                  ^
    
    Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'typescript' imported from /Users/danil.t/.npm/_npx/91854/lib/node_modules/typesafe-i18n/cli/typesafe-i18n.mjs
        at new NodeError (internal/errors.js:322:7)
        at packageResolve (internal/modules/esm/resolve.js:687:9)
        at moduleResolve (internal/modules/esm/resolve.js:728:18)
        at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:842:11)
        at Loader.resolve (internal/modules/esm/loader.js:89:40)
        at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
        at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:76:40)
        at link (internal/modules/esm/module_job.js:75:36) {
      code: 'ERR_MODULE_NOT_FOUND'
    }
    

    Reproduction

    create new nextjs app with ts, try to add typesafe-i18n

    Logs

    No response

    Config

    No response

    Additional information

    No response

    bug 
    opened by multipliedtwice 10
  • Wrong generated for esm

    Wrong generated for esm

    Version

    5.16.3

    Describe the bug

    When you setup an esm project, generated files are not correct.

    Reproduction

    First there is an issue to load typings from /detectors I had to had this types line to your package.json and in fact it's missing on all exports.

     "exports": {
            "./detectors": {
                "import": "./detectors/index.mjs",
                "require": "./detectors/index.cjs",
                "types": "./detectors/index.d.ts"
            },
    

    Furthermore, when you generate async utils it's missing the .js at the end of each imports.

    const localeNamespaceLoaders = {
      en: {
        app_404: () => import('./en/app_404'),
        app_activity: () => import('./en/app_activity'),
        app_ask: () => import('./en/app_ask'),
        'app_email-verified': () => import('./en/app_email-verified'),
        app_explore: () => import('./en/app_explore'),
        app_home: () => import('./en/app_home'),
      }
    }
    

    should be

    const localeNamespaceLoaders = {
      en: {
        app_404: () => import('./en/app_404.js'),
        app_activity: () => import('./en/app_activity.js'),
        app_ask: () => import('./en/app_ask.js'),
        'app_email-verified': () => import('./en/app_email-verified.js'),
        app_explore: () => import('./en/app_explore.js'),
        app_home: () => import('./en/app_home.js'),
      }
    }
    

    Logs

    TSC can't compile with these errors
    

    Config

    {
       "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json",
       "adapter": "react",
       "esmImports": true,
       "baseLocale": "en"
    }
    

    Additional information

    No response

    bug 
    opened by yovanoc 9
  • "Cannot find module" in yarn monorepo setup

    Version

    5.14.0

    Describe the bug

    Hi! I ran into a problem when using turborepo, if the module is added to one application, then everything works as it should. But when added to the second, the module starts to give an error when both are started.

    Applications are written in NextJS.

    Both times the module is connected and initialized according to the instructions.

    Reproduction

    install module auto setup module connected this to one more application in turborepo

    Logs

    Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Volumes/WORK/website/apps/admin/node_modules/typesafe-i18n/react' imported from /Volumes/WORK/website/apps/admin/.next/server/pages/_app.js
    Did you mean to import typesafe-i18n/react/index.cjs?
        at new NodeError (node:internal/errors:387:5)
        at finalizeResolution (node:internal/modules/esm/resolve:404:11)
        at moduleResolve (node:internal/modules/esm/resolve:965:10)
        at defaultResolve (node:internal/modules/esm/resolve:1173:11)
        at nextResolve (node:internal/modules/esm/loader:173:28)
        at ESMLoader.resolve (node:internal/modules/esm/loader:852:30)
        at ESMLoader.getModuleJob (node:internal/modules/esm/loader:439:18)
        at ESMLoader.import (node:internal/modules/esm/loader:536:22)
        at importModuleDynamically (node:internal/modules/cjs/loader:1059:29)
        at importModuleDynamicallyWrapper (node:internal/vm/module:438:21) {
      code: 'ERR_MODULE_NOT_FOUND',
      page: '/'
    }
    

    Config

    {
       "adapter": "react",
       "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json",
       "baseLocale": "en"
    }
    

    Additional information

    No response

    bug 
    opened by epicbytes 9
  • Upgrade to React 18

    Upgrade to React 18

    Version

    5.3.2

    Describe the bug

    Hi !, When I upgrade my project to React 18, I have this error.

    image

    Maybe, you should upgrade React in adapter-react

    Reproduction

    Classic install with React 18

    Logs

    No response

    Config

    {
       "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json",
       "baseLocale": "en",
       "adapter": "react"
    }
    

    Additional information

    No response

    bug 
    opened by Achaak 9
  • Jest fails to import detectors when testing in NodeJS

    Jest fails to import detectors when testing in NodeJS

    Describe the bug

    Hi,

    I've been trying to run my test since I added typesafe-i18n to my backend but I've been running into a problem. While testing manually to see if the translations were working right, everything seems to be working well but while running the tests, my tests that were testing files that used the translation were failing. It seems to fail to import the detectors in the utils file and causing everything else to fail.

    Reproduction

    cross-env NODE_ENV=test jest --verbose --maxWorkers=3
    

    Logs

    FAIL  tests/integration/mutations/productMutation/productCreate.test.ts
      ● Test suite failed to run
    
        Cannot find module 'typesafe-i18n/detectors' from 'src/i18n/i18n-util.ts'
    
        Require stack:
          src/i18n/i18n-util.ts
          src/i18n/i18n-node.ts
          src/i18n/index.ts
          src/graphql/resolvers/auditLogQuery/resolvers.ts
          src/graphql/resolvers/query/resolvers.ts
          src/graphql/index.ts
          tests/helpers/apolloServerHelper.ts
          tests/integration/mutations/productMutation/productCreate.test.ts
    
           6 | import type { Translation, TranslationFunctions, Formatters, Locales } from './i18n-types'
           7 | import type { LocaleDetector } from 'typesafe-i18n/detectors'
        >  8 | import { detectLocale as detectLocaleFn } from 'typesafe-i18n/detectors'
             | ^
           9 | import { initFormatters } from './formatters'
          10 |
          11 | export const baseLocale: Locales = 'en'
    
          at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:311:11)
          at Object.<anonymous> (src/i18n/i18n-util.ts:8:1)
    

    Config

    {
       "adapter": "node",
       "loadLocalesAsync": false,
       "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json"
    }
    

    Additional information

    I'm on MacOS and using NodeJS 16.9.0 and we're using Jest 27.0.4 & cross-env 7.0.3 for the project.

    I also tried adding typesafe-i18n --no-watch && in front of my test command to generate the translations before the tests but with no result. My suspicion is that there is a problem with how the subdirectory is imported (or setup on your side, I'm not really sure) because it fails at the line where the detector is imported but not the one where the i18nString, i18nObject function are imported.

    We also added a small wrapper around i18nObject which is why it's going through src/i18n/index.ts.

    // src/i18n/index.ts
    import { i18nObject } from './i18n-node';
    
    export const LL = i18nObject;
    

    We don't use the detector but we can't remove this particular code because it is generated each time. I'm a bit at a lost on what to do honestly so if you have any ideas on what can causes this, let me know.

    bug external-issue 
    opened by phil714 9
  • Calling translations with .apply or .call

    Calling translations with .apply or .call

    Describe the bug

    I'm using typesafe-i18n (which is by the way excellent) with Svelte.

    Everything is working great. I can write translations with

    $LL.my.translation.key()
    

    and it gets correctly translated.

    Now, my application is using Testcafe for end-to-end test. And in Testcafe, it is translated to:

    "my.translation.key.apply"
    

    Notice the "apply" at the end of the string. The thing is Testcafe is doing some black magic to the code and adding itself its own proxys.

    That should not be a typesafe-i18n issue... until I asked myself... what if I try to run:

    $LL.my.translation.key.apply([])
    

    With the current implementation of typesafe-i18n, typesafe-i18n looks for the "my.translation.key.apply" key. The syntax is ambiguous. In my opinion, it could also mean that we want to call the "$LL.my.translation.key" method.

    Same remark applies for the "call" method.

    $LL.my.translation.key.call([])
    

    So this is both an issue and a question.

    Shouldn't the get method of the proxy used by typesafe-i18n not ignore "apply" and "call" keys? (which could be a breaking changes for users that use "apply" and "call" keys in their translations.

    Reproduction

    Simply try to translate any string by using the Javascript ".apply()" method

    Logs

    No response

    Config

    No response

    Additional information

    No response

    bug 
    opened by moufmouf 8
  • Splitting translation into multiple files causes reload issues

    Splitting translation into multiple files causes reload issues

    To avoid a massive translation file I have opted to split it into parts e.g.

    i18n/en/index.ts
    i18n/en/publish.copy.ts
    i18n/en/unPublish.copy.ts
    ...
    

    If the copy is inside the index.ts file then any changes will be mirrored in i18n-types.ts rather quickly. But if I make changes to any of the other files (which in turn are included in index.ts) then the types are not updated. (when restarting typesafe it is updated however).

    It should be noted that the library does pick up that files have been changed, but the types are not updated.

    bug help wanted 
    opened by mullwaden 8
  • Cannot use `import.meta` with Sveltekit

    Cannot use `import.meta` with Sveltekit

    Version

    4.5.0

    Describe the bug

    I'm trying to conditionally build translation strings based on env variables in a Sveltekit project. But I cannot use import.meta.env which Sveltekit uses via Vite.

    1. Translation doesn't work (see error in logs).
    2. TranslationFunctions is empty {}.

    Reproduction

    Repo: https://github.com/sidvishnoi/typesafe-i18n-demo-sveltekit-jsdoc See: https://github.com/sidvishnoi/typesafe-i18n-demo-sveltekit-jsdoc/blob/main/src/i18n/en/index.ts

    Run: PROJECT_ID=project1 pnpm dev and PROJECT_ID=project2 pnpm dev

    Logs

    [typesafe-i18n] version 4.5.0
    [typesafe-i18n] generating files for TypeScript version: '4.6.x'
    [typesafe-i18n] options: { adapter: 'svelte', esmImports: true }
    [typesafe-i18n] watcher started in: './src/i18n/'
    [typesafe-i18n] ERROR: import failed for /path/to/node_modules/typesafe-i18n/temp-output/11/en/index.js SyntaxError: Cannot use 'import.meta' outside a module
    [typesafe-i18n] ERROR: could not read default export from base locale file 'en'
    [typesafe-i18n] ... all files are up to date
    

    Config

    {
      "adapter": "svelte",
      "esmImports": true,
      "outputPath": "./src/i18n",
      "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json"
    }
    

    Additional information

    No response

    bug 
    opened by sidvishnoi 7
  • Generator doesn't create files in new project

    Generator doesn't create files in new project

    Version

    5.13.0

    Describe the bug

    npx typesafe-i18n --setup is successful but no files have been generated:

    $ mkdir test-app
    
    $ cd test-app
    
    $ yarn add typescript
    yarn add v1.22.17
    info No lockfile found.
    [1/4] 🔍  Resolving packages...
    [2/4] 🚚  Fetching packages...
    [3/4] 🔗  Linking dependencies...
    [4/4] 🔨  Building fresh packages...
    
    success Saved lockfile.
    success Saved 1 new dependency.
    info Direct dependencies
    └─ [email protected]
    info All dependencies
    └─ [email protected]
    ✨  Done in 0.52s.
    
    $ npx typesafe-i18n --setup
    [typesafe-i18n] version 5.13.0
    [typesafe-i18n] See this link for more information on how to setup this project: https://github.com/ivanhofer/typesafe-i18n#options
    ✔ What is your base locale? … en
    ✔ What adapter do you want to use? › None
    ✔ Are you using esm modules in your project? › No / not sure
    ✔ Are you using TypeScript or JavaScript? › TypeScript
    ✔ Where do you want your locale files to be located? … ./src/i18n/
    [typesafe-i18n] generated config file: '.typesafe-i18n.json'
    [typesafe-i18n] installing dependencies ...
    warning package.json: No license field
    warning No license field
    warning No license field
    yarn add v1.22.17
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    [3/4] Linking dependencies...
    [4/4] Building fresh packages...
    success Saved lockfile.
    success Saved 1 new dependency.
    info Direct dependencies
    └─ [email protected]
    info All dependencies
    └─ [email protected]
    Done in 0.24s.
    
    [typesafe-i18n] WARNING: could not add 'typesafe-i18n' script to 'package.json'. You need to add it manually.
    
    If you are using this project in a commercial environment please consider sponsoring 'typesafe-i18n':
    https://github.com/sponsors/ivanhofer
    
    $ ls
    node_modules	package.json	yarn.lock
    
    

    Reproduction

    See above.

    Logs

    No response

    Config

    No response

    Additional information

    No response

    bug 
    opened by OliverJAsh 6
Owner
Hofer Ivan
passion for modern technologies, TypeScript, Svelte, innovative UI/UX concepts and performance optimizations
Hofer Ivan
Framework agnostic CLI tool for routes parsing and generation of a type-safe helper for safe route usage. 🗺️ Remix driver included. 🤟

About routes-gen is a framework agnostic CLI tool for routes parsing and generation of a type-safe helper for safe route usage. Think of it as Prisma,

Stratulat Alexandru 192 Jan 2, 2023
100% type-safe query builder for node-postgres :: Generated types, call any function, tree-shakable, implicit type casts, and more

⚠️ This library is currently in alpha. Contributors wanted! tusken Postgres client from a galaxy far, far away. your database is the source-of-truth f

alloc 54 Dec 29, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Type-safe session for all Astro SSR project

Astro Session Why use Astro Session? When building server application with Astro, you will often need session system to identify request coming from t

Steven Yung 8 Dec 19, 2022
🐬 A simplified implementation of TypeScript's type system written in TypeScript's type system

?? HypeScript Introduction This is a simplified implementation of TypeScript's type system that's written in TypeScript's type annotations. This means

Ronen Amiel 1.8k Dec 20, 2022
Transpile TypeScript to Espruino flavor of JavaScript for ESP8266/ESP32 microcontrollers template project. Writing safe, maintainable, and testable code is the projects goal.

ESP-TypeScript Transpile TypeScript to Espruino flavor of JavaScript for ESP8266/ESP32 microcontrollers template project. Writing safe, maintainable,

Spencer Kittleson 152 Dec 20, 2022
A lightweight, fully-featured, modular, typescript-compatible javascript library for Paymongo.

paymongo.js A lightweight, fully-featured, modular, typescript-compatible javascript library for PayMongo. Installation npm install paymongo.js # or y

Prince Carlo Juguilon 15 Nov 23, 2022
A functional, immutable, type safe and simple dependency injection library inspired by angular.

func-di English | 简体中文 A functional, immutable, type safe and simple dependency injection library inspired by Angular. Why func-di Installation Usage

null 24 Dec 11, 2022
Type safe library for interacting with Mindbody's Public API (v6) and Webhooks

Mindbody API Type safe library for interacting with Mindbody's Public API (v6) and Webhooks ⚠️ Read before installing This library is typed according

SplitPass 4 Dec 9, 2022
A zero-dependency, buildless, terse, and type-safe way to write HTML in JavaScript.

hdot A sensible way to write HTML in JavaScript. Type-safe. Helps you follow the HTML spec. Terse. Almost character for character with plain HTML. Bui

Will Martin 31 Oct 24, 2022
Combine type and value imports using Typescript 4.5 type modifier syntax

type-import-codemod Combines your type and value imports together into a single statement, using Typescript 4.5's type modifier syntax. Before: import

Ian VanSchooten 4 Sep 29, 2022
A type programming language which compiles to and interops with type-level TypeScript

Prakaar Prakaar (hindi for "type") is a type programming language which compiles to and interops with type-level TypeScript. Prakaar itself is also a

Devansh Jethmalani 17 Sep 21, 2022
A transpiler from golang's type to typescript's type for collaboration between frontend & backend.

go2type go2type.vercel.app (backup site) A typescript transpiler that convert golang's type to typescript's type. Help front-end developer to work fas

Oanakiaja 8 Sep 26, 2022
Cloudy is a set of constructs for the AWS Cloud Development Kit that aim to improve the DX by providing a faster and type-safe code environment.

cloudy-ts These packages aren't yet published on npm. This is still highly experimental. Need to figure out a few things before releasing the first ve

Cristian Pallarés 5 Nov 3, 2022
A script that combines a folder of SVG files into a single sprites file and generates type definitions for safe usage.

remix-sprites-example A script that combines a folder of .svg files into a single sprites.svg file and type definitions for safe usage. Technical Over

Nicolas Kleiderer 19 Nov 9, 2022
Build type-safe web apps with PureScript.

PUX Build type-safe web applications with PureScript. Documentation | Examples | Chat Pux is a PureScript library for building web applications. Inter

Alex Mingoia 567 Jun 18, 2022
Type Safe Object Notation & Validation

tson Type Safe Object Notation & Validation ?? Work in Progress, not ready for production... Features ?? Functional ?? Immutable ✅ Well tested Why? Af

null 9 Aug 10, 2022