i18n icon indicating copy to clipboard operation
i18n copied to clipboard

$t() autocomplete support

Open EternalC0der opened this issue 3 years ago • 9 comments

Describe the feature

Hello, It would be really nice to have auto completion feature while using t('welcome') in template, especially when you want to reuse keys in different sections.

Additional information

  • [ ] Would you be willing to help implement this feature?
  • [ ] Could this feature be implemented as a module?

Final checks

EternalC0der avatar Dec 20 '22 17:12 EternalC0der

Hi! I'll support about auto complete. vue-i18n v9 has type-safe resources feature. https://vue-i18n.intlify.dev/guide/advanced/typescript.html

we need to setup manually in vue-i18n. In nuxt, I will support auto complete by respecting the defaultLocale and dynamically generating types with that resource as master schema.

I would also like to support $t, but we need to refactor the $t type definition on the vue-i18n side. related issue on vue-i18n: https://github.com/intlify/vue-i18n-next/issues/1124

kazupon avatar Dec 20 '22 17:12 kazupon

@kazupon Any news on when we can expect this to be shipped? It would be a real step forward for developer experience in my opinion :)

jenseo avatar Oct 10 '23 06:10 jenseo

Any update on this?

natemate90 avatar Nov 20 '23 13:11 natemate90

I have been waiting for this feature for so long 😂 Any updates?

Here is a quick solution to get the list of locale keys, I wrote this to manually add type-safety for my code. I hope it helps others:

import english from '~/i18n/en-US.json'

type StringKey<T> = Extract<keyof T, string>
type GenerateKeyPaths<T, Prefix extends string = ''> = T extends object
  ? { [K in StringKey<T>]: T[K] extends object ? GenerateKeyPaths<T[K], `${Prefix}${K}.`> : `${Prefix}${K}` }[StringKey<T>]
  : Prefix

type Locale = typeof english
export type I18nKeys = GenerateKeyPaths<Locale>

EternalC0der avatar Mar 23 '24 11:03 EternalC0der

@EternalC0der how are you using that? Are you making a custom translation function that then uses I18nKeys?

This works if we use t from useI18n

import "vue-i18n";
import en from "./i18n/website/en.json";

type MainTranslations = typeof en;
declare module "vue-i18n" {
	export interface DefineLocaleMessage extends MainTranslations {}
}

but it doesn't work with $t because the generated types for $t are incorrect. There's like 10 different overrides for it so I dont really want to override them all like above

Bobakanoosh avatar May 09 '24 02:05 Bobakanoosh

@kazupon I was able to get type-safe checking as well as auto-completion to work for the @nuxtjs/i18n $t function (and others) by manually overriding the interface for the given function(s).

I believe this could also be extended for type checking the methods exported like const { t } = useI18n() usage as well if implemented correctly.

I was going to attempt to PR the feature into the upstream repository; however, there appear to be around 19 different interfaces for the $t function in the resolved vue-i18n/dist/vue-i18n.d.ts file and I'm not sure where to start?

adamdehaven avatar Jun 04 '24 00:06 adamdehaven

Managed to get key autocompletion by adding a i18n.d.ts in my types folder (at root of project).

import fr from "~/i18n/fr";

type StringKey<T> = Extract<keyof T, string>;
type GenerateKeyPaths<T, Prefix extends string = ""> = T extends object
  ? {
      [K in StringKey<T>]: T[K] extends object
        ? GenerateKeyPaths<T[K], `${Prefix}${K}.`>
        : `${Prefix}${K}`;
    }[StringKey<T>]
  : Prefix;

type Locale = typeof fr;

declare global {
  type I18nKeys = GenerateKeyPaths<Locale>;
}

declare module "vue" {
  interface ComponentCustomProperties {
    $t(key: I18nKeys): string;
  }
}

#2591

thomaslecoeur avatar Jul 13 '24 08:07 thomaslecoeur

Managed to get key autocompletion by adding a i18n.d.ts in my types folder (at root of project).

import fr from "~/i18n/fr";

type StringKey<T> = Extract<keyof T, string>;
type GenerateKeyPaths<T, Prefix extends string = ""> = T extends object
  ? {
      [K in StringKey<T>]: T[K] extends object
        ? GenerateKeyPaths<T[K], `${Prefix}${K}.`>
        : `${Prefix}${K}`;
    }[StringKey<T>]
  : Prefix;

type Locale = typeof fr;

declare global {
  type I18nKeys = GenerateKeyPaths<Locale>;
}

declare module "vue" {
  interface ComponentCustomProperties {
    $t(key: I18nKeys): string;
  }
}

#2591

Thanks! This helped me get the autocomplete working! 🙏 One small modification I made to make it work is, because I use .ts files with a default export:

// lang/en.ts
export default {
  welcome: "Welcome"
}

I had to change the config to

import type en from "./lang/en";

type StringKey<T> = Extract<keyof T, string>;
type GenerateKeyPaths<T, Prefix extends string = ""> = T extends object
  ? {
      [K in StringKey<T>]: T[K] extends object
        ? GenerateKeyPaths<T[K], `${Prefix}${K}.`>
        : `${Prefix}${K}`;
    }[StringKey<T>]
  : Prefix;

// IMPORTANT CHANGE HERE, USING AWAITED + RETURN TYPE
type Locale = Awaited<ReturnType<typeof en>>;

declare global {
  type I18nKeys = GenerateKeyPaths<Locale>;
}

declare module "vue" {
  interface ComponentCustomProperties {
    $t(key: I18nKeys): string;
  }
}

Also, remember to add the .d.ts file in your tsconfig.json file:

// tsconfig.json
{
 // ...

  "compilerOptions": {
    "types": ["./i18n.d.ts"]
  }
}

In case it helps anybody ✌️

dsijakovski98 avatar Sep 20 '24 09:09 dsijakovski98

The latest v9 release candidate (https://github.com/nuxt-modules/i18n/releases/tag/v9.0.0-rc.2) includes experimental vue-i18n options and messages generation, this provides autocompletion for translation functions, please try it out and let me know if this works as expected 🙏

More on the option that enables this functionality: https://i18n.nuxtjs.org/docs/v9/options/misc#experimentaltypedoptionsandmessages, the PR implementing this has a demo video of it in action https://github.com/nuxt-modules/i18n/pull/3151

BobbieGoede avatar Oct 07 '24 21:10 BobbieGoede

Closing this as we have experimental support for this in the stable release of v9, please try it out and let me know your thoughts!

BobbieGoede avatar Nov 03 '24 16:11 BobbieGoede

let me know your thoughts!

It works like a charm for me! Absolutely love it!

sneakylenny avatar Dec 18 '24 11:12 sneakylenny

The latest v9 release candidate (https://github.com/nuxt-modules/i18n/releases/tag/v9.0.0-rc.2) includes experimental vue-i18n options and messages generation, this provides autocompletion for translation functions, please try it out and let me know if this works as expected 🙏

More on the option that enables this functionality: https://i18n.nuxtjs.org/docs/v9/options/misc#experimentaltypedoptionsandmessages, the PR implementing this has a demo video of it in action #3151

Hi @BobbieGoede, many thanks for your efforts to implement this. Is there any updated documentation on how we can get the message schema to work? The link you mention doesn't work anymore, maybe it's default behavior now? I can't get $t autocomplete to work yet in my existing project, maybe I'm doing something wrong. Would you mind shortly describing on what steps are needed to get the message schema to be generated?

Many thanks in advance

natemate90 avatar Feb 13 '25 12:02 natemate90

The docs for v9 were moved up a level, the updated link is https://i18n.nuxtjs.org/docs/api/options#typedoptionsandmessages, let me know if you run into issues (preferably with a reproduction 🙏)

BobbieGoede avatar Feb 13 '25 13:02 BobbieGoede

@BobbieGoede Works excellent, many thanks!

natemate90 avatar Feb 14 '25 10:02 natemate90

The docs for v9 were moved up a level, the updated link is https://i18n.nuxtjs.org/docs/api/options#typedoptionsandmessages, let me know if you run into issues (preferably with a reproduction 🙏)

Works for me too, but it would be nice to have incorrect keys as a typescript error if possible.

murshex avatar Mar 05 '25 00:03 murshex