React i18next - Custom formatter doesn't work - internationalization

I'm using ICU format and would like to add a custom formatter that will lowercase a string.
To do so I've used this configuration
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enTranslation from "./locales/en/translation.json"
import LanguageDetector from 'i18next-browser-languagedetector';
import ICU from 'i18next-icu';
i18n
.use(LanguageDetector)
.use(ICU)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,
initImmediate: false,
resources: {
en: enTranslation
},
lng: "en", // if you're using a language detector, do not define the lng option
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
}
});
i18n.services.formatter?.add("lowercase", (value, lng, options) => {
return value.toLowerCase();
});
export default i18n;
I load this configration into my index.tsx
import './i18n';
translation.json
{
"translation": {
"custom-format": "Example {value, lowercase}."
}
}
If I try and use this message it just prints out the options. E.g.
// Prints as "Example {value, lowercase}."
<Trans i18nKey="custom-format" values={{value: "MiXtUrE"}}/>
I've checked if the formatter exists in the i18next object and it does. It is however missing its name.
Why won't it use the custom formatter?

Related

Vite Library Mode Build Different between Windows and Linux

This is a crosspost from my github discussion, but I wanted to see if anyone has any thoughts here.
I'm using vite for an npm package that's in "library mode." I have 2 files:
utilities.ts
export function thisGetsRemovedInBundle() {
console.log('This should be in the bundle!');
}
export function thisIsUsed() {
console.log('Used!');
return 1;
}
components/index.ts
import { thisIsUsed } from '../utilities';
export default {
Hello: thisIsUsed(),
};
vite.config.ts
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: 'components/index.ts',
formats: ['es'],
},
rollupOptions: {
external: ['vue'],
input: {
index: 'components/index.ts',
utilities: 'utilities.ts',
},
output: {
dir: 'dist',
format: 'es',
entryFileNames: '[name].js',
},
},
},
});
When I build this on a Windows 10 machine, it produces the following in index.js:
function thisIsUsed() {
console.log("Used!");
return 1;
}
var index = {
Hello: thisIsUsed()
};
export { index as default };
On Ubuntu, it produces this:
import { thisIsUsed } from "./utilities.js";
var index = {
Hello: thisIsUsed()
};
export { index as default };
Notice in the Windows build, it doesn't import the function but rather adds it as if it's part of index.js. I would expect it to be like the latter because in the Windows bundle, it has duplicated code (both files have a copy of thisIsUsed).
Is there some fundamental npm or node magic that I'm missing between these builds? If so, how do I solve this issue so my build always looks like the Ubuntu build (without having to use a Linux machine or Unix shell).
I ended up reporting a bug here, and while it appears valid, it can be fixed easily by using path.resolve and __dirname when defining the path to the input files. e.g. in the vite.config.ts above, it should be:
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: 'components/index.ts',
formats: ['es'],
},
rollupOptions: {
external: ['vue'],
input: {
index: path.resolve(__dirname, 'components/index.ts'),
utilities: path.resolve(__dirname, 'utilities.ts'),
},
output: {
dir: 'dist',
format: 'es',
entryFileNames: '[name].js',
},
},
},
});

How to use useI18n inside vue3 composition api?

I'm using vue-i18n in conjunction with quasar + vue 3 composition api but I get an error as following
SyntaxError: 19 vendor.49822a76.js:formatted:926 SyntaxError: 19 (at vendor.49822a76.js:formatted:27825:21)
at F (vendor.49822a76.js:formatted:27825:21)
at Pt (vendor.49822a76.js:formatted:29590:20)
at vn (vendor.49822a76.js:formatted:30617:27)
at 238.35491042.js:1:419
at f (vendor.49822a76.js:formatted:883:25)
at p (vendor.49822a76.js:formatted:892:27)
Error In console when using useI18n
and here is my i18n file:
Boot directory:
import { boot } from 'quasar/wrappers'
import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'
export default boot(({ app }) => {
const i18n = createI18n({
locale: 'ar',
messages
})
// Set i18n instance on app
app.use(i18n)
})
My Vue File
import { useI18n } from 'vue-i18n';
import AppService from "../../services/api";
export default defineComponent({
setup() {
const { t } = useI18n();
console.log(t)
}
})
any clue?
You need specify allowComposition: true to createI18n options.
Here is the link to the documentaion

vuepress local search not showing up [version 2.0.0-beta.22]

I am new to vueppress.
I followed the docs here to create a documentation site. things went well but the search field/input didn't show up. I tried to follow the plugin installation docs here but I got:
I need to install #vuepress/shared-utils
after that I had to install #vue/component-compiler-utils too
but was unable to see the search input. I also tried to add the following to my ./docs/.vuepress/config.ts but still no luck.
plugins: [
[
'#vuepress/plugin-search',
{
searchMaxSuggestions: 10
}
],
]
I don't want to use Algoia search as this is internal documentation.
I had the same issue. Everything was working except the search box was not visible.
The issue was that my ...docs/.vuepress/config.ts was not structured properly. To fix it I followed exactly what the VuePress documentation instructed.
The working config.ts structure
import { defaultTheme } from '#vuepress/theme-default'
import { searchPlugin } from '#vuepress/plugin-search'
module.exports = {
theme: defaultTheme({
...
}),
plugins: [
searchPlugin({
...
})
]
}
Currently I am using VuePress v2.0.0-beta.45
and I used the following to install what I needed:
npm i -D #vuepress/plugin-search#next
npm i -D #vuepress/plugin-register-components#next
Detailed config.ts that is working for me
import { path } from '#vuepress/utils'
import { defaultTheme } from '#vuepress/theme-default'
// Plugins
import { searchPlugin } from '#vuepress/plugin-search'
import { registerComponentsPlugin } from '#vuepress/plugin-register-components'
import navBarItems from './public/navbar'
import sideBar from './public/sidebar'
// SEE: https://v2.vuepress.vuejs.org/reference/default-theme/config.html#config
module.exports = {
// Site Config: https://v2.vuepress.vuejs.org/reference/config.html#site-config
lang: 'en-US',
title: 'Title on Tab and Navbar',
description: '',
// https://v2.vuepress.vuejs.org/reference/default-theme/config.html
theme: defaultTheme({
logo: 'logo-light.png',
logoDark: 'logo-dark.png',
//https://v2.vuepress.vuejs.org/reference/default-theme/config.html#navbar
navbar: navBarItems,
// https://v2.vuepress.vuejs.org/reference/default-theme/config.html#sidebar
sidebar: sideBar
}),
plugins: [
// https://v2.vuepress.vuejs.org/reference/plugin/register-components.html
registerComponentsPlugin({
componentsDir: path.resolve(__dirname, './components')
}),
// https://v2.vuepress.vuejs.org/reference/plugin/search.html#search
searchPlugin({
// getExtraFields: (page) => page.frontmatter.tags,
maxSuggestions: 15,
hotKeys: ['s', '/'],
locales: {
'/': {
placeholder: 'Search',
}
}
})
],
}
Note that I keep my sidebar array and navbar object in different files.
Also I couldn't find any TypeScript reference for the config in VuePress 2x

NestJS + GraphQL Federation and schema first GraphQLDefinitionsFactory

I'am trying to use the GraphQL federation with the schema first approach. Before I switch to federation, I was using ts-node and a little script to generate my typings like this :
import { GraphQLDefinitionsFactory } from '#nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.schema.ts'),
outputAs: 'class',
});
This was working well until I switch to the federation approach and modifying my schema adding the #Key() directive in my sites.graphql file (schema first!) :
type Site #key(fields: "siteId") {
siteId: ID!
contractId: Int
dateStart: String
siteName: String
}
type Query {
GetSite(id: ID!): Site
}
Now, when I generate my classes, I have the following error :
> ts-node src/tools/generate-typings.ts
(node:84388) UnhandledPromiseRejectionWarning: Error: Unknown directive "#key".
The #key directive does not seem to be recognized. Do I miss something?
Thank you for your help
Ok, digging in the source code of graphql-definitions.factory.ts I found an undocumented option federation.
Changing my script to :
import { GraphQLDefinitionsFactory } from '#nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.schema.ts'),
outputAs: 'class',
federation: true
});
And it works now.
Ps: to run the project, don't forget to eventually disable the installSubscriptionHandlers in the GraphQLModule options.
For federated subgraphs you should used GraphQLFederationDefinitionsFactory instead:
import { join } from 'path';
import { GraphQLFederationDefinitionsFactory } from '#nestjs/graphql';
const definitionsFactory = new GraphQLFederationDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
defaultScalarType: 'unknown',
customScalarTypeMapping: {
DateTime: 'Date',
},
watch: true,
});
I have created the script to generate the federation schema
import { writeFileSync, readFileSync } from 'fs';
import { buildSubgraphSchema } from '#apollo/subgraph';
import { printSchema, DocumentNode } from 'graphql';
import gql from 'graphql-tag';
async function generateSchema() {
// auto generate schema file
const subGraphschema = readFileSync('./src/schema/schema.graphql', {
encoding: 'utf8',
flag: 'r',
});
const schema: DocumentNode = gql(subGraphschema);
const generatedSchema = buildSubgraphSchema({
typeDefs: schema,
});
writeFileSync(
'./public/schema.graphql',
printSchema(generatedSchema),
'utf8',
);
console.log(`Generated GraphQL schema:\n\n${printSchema(generatedSchema)}`);
}
generateSchema();

JHipster: I can't add thiered party dependency like 'angular-2-dropdown-multiselect'

I have added angular2-dropdown-multiselect in Jhipster angular part. Its not working perfectly as per the angular2-dropdwon-multi select or ngx-treeview I have added the dependency using
npm install angular2-multiselect-dropdown --save
Then I have added the same into app.module.ts
import { AngularMultiSelectModule } from 'angular2-multiselect-dropdown/angular2-multiselect-dropdown';
#NgModule({
// ...
imports: [
AngularMultiSelectModule,
]
// ...
})
Then Try this following example
import { Component, OnInit } from '#angular/core';
export class AppComponent implements OnInit {
dropdownList = [];
selectedItems = [];
dropdownSettings = {};
ngOnInit(){
this.dropdownList = [
{"id":1,"itemName":"India"},
{"id":2,"itemName":"Singapore"},
{"id":3,"itemName":"Australia"},
{"id":4,"itemName":"Canada"},
{"id":5,"itemName":"South Korea"},
{"id":6,"itemName":"Germany"},
{"id":7,"itemName":"France"},
{"id":8,"itemName":"Russia"},
{"id":9,"itemName":"Italy"},
{"id":10,"itemName":"Sweden"}
];
this.selectedItems = [
{"id":2,"itemName":"Singapore"},
{"id":3,"itemName":"Australia"},
{"id":4,"itemName":"Canada"},
{"id":5,"itemName":"South Korea"}
];
this.dropdownSettings = {
singleSelection: false,
text:"Select Countries",
selectAllText:'Select All',
unSelectAllText:'UnSelect All',
enableSearchFilter: true,
classes:"myclass custom-class"
};
}
onItemSelect(item:any){
console.log(item);
console.log(this.selectedItems);
}
OnItemDeSelect(item:any){
console.log(item);
console.log(this.selectedItems);
}
onSelectAll(items: any){
console.log(items);
}
onDeSelectAll(items: any){
console.log(items);
}
}
with HTML
<angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems"
[settings]="dropdownSettings"
(onSelect)="onItemSelect($event)"
(onDeSelect)="OnItemDeSelect($event)"
(onSelectAll)="onSelectAll($event)"
(onDeSelectAll)="onDeSelectAll($event)">
</angular2-multiselect>
But after runing yarn serve
it just showing
Please help me
I had a similar problem with another third party library (ngx-treeview) and I also was only getting the html component empty and with no errors in the javascript console.
It was solved after importing the third party library properly following the JHipster project structure. If you want to use an external module in more than one module component, which is common, you need to configure it in shared-libs.module.ts and also add it to imports and to the exports on its #NgModule configuration.
src\main\webapp\app\shared\shared-libs.module.ts
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { CommonModule } from '#angular/common';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { NgJhipsterModule } from 'ng-jhipster';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { CookieModule } from 'ngx-cookie';
import { FontAwesomeModule } from '#fortawesome/angular-fontawesome';
import { TreeviewModule } from 'ngx-treeview';
#NgModule({
imports: [
NgbModule.forRoot(),
NgJhipsterModule.forRoot({
alertAsToast: false,
i18nEnabled: true,
defaultI18nLang: 'en'
}),
InfiniteScrollModule,
CookieModule.forRoot(),
FontAwesomeModule,
TreeviewModule.forRoot() // new third party lib import
],
exports: [FormsModule, CommonModule, NgbModule, NgJhipsterModule,
InfiniteScrollModule, FontAwesomeModule,
TreeviewModule] // new third party lib export
})
export class MyProjectSharedLibsModule {}
Share-libs module is generated by Jhipster and it is by default imported in shared.module which is imported by app.module and also the other modules that are created at start by Jhipster. For more about project structure: https://www.jhipster.tech/using-angular/
However, if you create a new angular module component you need to add the shared module in the imports to be able to use the third parties libraries there.
#NgModule({
...
imports: [MyProjectSharedModule,
RouterModule.forChild([HOME_ROUTE])],
..
})
export class MyProjectAnotherModule {}

Resources