i18next datetime formatting not working in expo project - internationalization

My i18.js file (imported in App.js)
[See EDIT below]
My en.json file
{
home: {
"time": "{{stime, datetime}} to {{etime, datetime}}",
}
}
Translation code in the component
const i18timeFormat = { hour: "numeric", minute: "numeric", hour12: true };
return (
<Text>
t("home.time",
{{
stime: starttime,
etime: endtime,
formatParams: { stime: i18timeFormat, etime: i18timeFormat },
}}
)
</Text>
);
Expected output
8:30 am to 10:30 am
Actual output
Wed Apr 13 2022 08:30:12 GMT+0530 (IST) to Wed Apr 13 2022 10:30:12 GMT+0530 (IST)
I've also tried the official example. Even it doesn't format. Anything I can try to fix it?
EDIT:
I've added the following packages to polyfill intl datetime and relative time.
"#formatjs/intl-datetimeformat": "^5.0.1",
"#formatjs/intl-getcanonicallocales": "^1.9.2",
"#formatjs/intl-locale": "^2.4.47",
"#formatjs/intl-numberformat": "^7.4.3",
"#formatjs/intl-pluralrules": "^4.3.3",
"#formatjs/intl-relativetimeformat": "^10.0.1",
i18.js file
import "#formatjs/intl-getcanonicallocales/polyfill";
import "#formatjs/intl-locale/polyfill-force";
import "#formatjs/intl-numberformat/polyfill-force";
import "#formatjs/intl-pluralrules/polyfill-force";
import "#formatjs/intl-datetimeformat/polyfill-force";
import "#formatjs/intl-datetimeformat/locale-data/en";
import "#formatjs/intl-datetimeformat/add-all-tz"; // Add ALL tz data
import "#formatjs/intl-relativetimeformat/polyfill-force";
import "#formatjs/intl-relativetimeformat/locale-data/en";
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import * as Localization from "expo-localization";
import en from "./i18n/en.json";
const resources = {
en: { translation: en }
};
i18n.use(initReactI18next).init({
resources,
lng: "en",
fallbackLng: "en",
});
export default i18n;
EDIT 2:
The warning after debug is set to true.
Missing locale data for
at node_modules/#formatjs/intl-localematcher/abstract/utils.js:8:14 in invariant
at node_modules/#formatjs/intl-localematcher/abstract/ResolveLocale.js:25:8 in ResolveLocale
at node_modules/#formatjs/ecma402-abstract/NumberFormat/InitializeNumberFormat.js:31:12 in InitializeNumberFormat
at node_modules/#formatjs/intl-numberformat/src/core.js:37:4 in exports.NumberFormat
at node_modules/#formatjs/intl-datetimeformat/src/abstract/FormatDateTimePattern.js:51:13 in FormatDateTimePattern
at node_modules/#formatjs/intl-datetimeformat/src/abstract/FormatDateTime.js:11:16 in FormatDateTime
at node_modules/i18next/dist/cjs/i18next.js:1800:24 in formats.reduce$argument_0
at node_modules/i18next/dist/cjs/i18next.js:1789:19 in format
at node_modules/i18next/dist/cjs/i18next.js:1581:30 in todos.forEach$argument_0
at node_modules/i18next/dist/cjs/i18next.js:1576:6 in interpolate
at node_modules/i18next/dist/cjs/i18next.js:843:14 in extendTranslation
at node_modules/i18next/dist/cjs/i18next.js:806:14 in translate
at src/components/gate/timeBlock/index.js:74:10 in TimeBlock

Like with the new plural rules: https://www.i18next.com/how-to/faq#why-are-my-plural-keys-not-working
You may also use other polyfills for the in-built formats: https://www.i18next.com/translation-function/formatting

Related

React i18next - Custom formatter doesn't work

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?

External Store File

I've created an Alpine store like the example:
import Alpine from 'alpinejs'
Alpine.store('darkMode', {
on: false,
toggle() {
this.on = ! this.on
}
})
Alpine.start()
Is there a way I can export the store to an external file and import it, as you can do with plugins etc.?
Yes, you can simply create a separate store.js file with the store definition:
import Alpine from 'alpinejs'
Alpine.store('darkMode', {
on: false,
toggle() {
this.on = ! this.on
}
})
And from the main.js (or equivalent) import the store.js file:
import Alpine from 'alpinejs'
import './store.js'
Alpine.start()
(I used Vite for testing.)

Customizing CKEditor for Strapi gives "ckeditor-duplicated-modules" error

I tried to modify this repo to customize CKEditor I want to use in my Strapi project. I added a lot more plugins, this is what my ckeditor.js file looks like:
import ClassicEditorBase from '#ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Alignment from '#ckeditor/ckeditor5-alignment/src/alignment.js';
import Autoformat from '#ckeditor/ckeditor5-autoformat/src/autoformat.js';
import BlockQuote from '#ckeditor/ckeditor5-block-quote/src/blockquote.js';
import Bold from '#ckeditor/ckeditor5-basic-styles/src/bold.js';
import CKFinder from '#ckeditor/ckeditor5-ckfinder/src/ckfinder.js';
import CKFinderUploadAdapter from '#ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter.js';
import EasyImage from '#ckeditor/ckeditor5-easy-image/src/easyimage';
import Essentials from '#ckeditor/ckeditor5-essentials/src/essentials';
import FontBackgroundColor from '#ckeditor/ckeditor5-font/src/fontbackgroundcolor.js';
import FontColor from '#ckeditor/ckeditor5-font/src/fontcolor.js';
import FontSize from '#ckeditor/ckeditor5-font/src/fontsize.js';
import FontFamily from '#ckeditor/ckeditor5-font/src/fontfamily.js';
import Heading from '#ckeditor/ckeditor5-heading/src/heading.js';
import HorizontalLine from '#ckeditor/ckeditor5-horizontal-line/src/horizontalline.js';
import Image from '#ckeditor/ckeditor5-image/src/image.js';
import ImageCaption from '#ckeditor/ckeditor5-image/src/imagecaption.js';
import ImageResize from '#ckeditor/ckeditor5-image/src/imageresize.js';
import ImageStyle from '#ckeditor/ckeditor5-image/src/imagestyle.js';
import ImageToolbar from '#ckeditor/ckeditor5-image/src/imagetoolbar.js';
import ImageUpload from '#ckeditor/ckeditor5-image/src/imageupload.js';
import Indent from '#ckeditor/ckeditor5-indent/src/indent.js';
import IndentBlock from '#ckeditor/ckeditor5-indent/src/indentblock.js';
import Italic from '#ckeditor/ckeditor5-basic-styles/src/italic.js';
import Link from '#ckeditor/ckeditor5-link/src/link.js';
import List from '#ckeditor/ckeditor5-list/src/list.js';
import MediaEmbed from '#ckeditor/ckeditor5-media-embed/src/mediaembed.js';
import MediaEmbedToolbar from '#ckeditor/ckeditor5-media-embed/src/mediaembedtoolbar.js';
import PageBreak from '#ckeditor/ckeditor5-page-break/src/pagebreak.js';
import Paragraph from '#ckeditor/ckeditor5-paragraph/src/paragraph';
import PasteFromOffice from '#ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';
import SimpleUploadAdapterStrapi from 'ckeditor5-upload-strapi/src/adapters/simpleuploadadapterstrapi';
import SpecialCharacters from '#ckeditor/ckeditor5-special-characters/src/specialcharacters.js';
import SpecialCharactersEssentials from '#ckeditor/ckeditor5-special-characters/src/specialcharactersessentials.js';
import SpecialCharactersArrows from '#ckeditor/ckeditor5-special-characters/src/specialcharactersarrows.js';
import SpecialCharactersCurrency from '#ckeditor/ckeditor5-special-characters/src/specialcharacterscurrency.js';
import SpecialCharactersLatin from '#ckeditor/ckeditor5-special-characters/src/specialcharacterslatin.js';
import SpecialCharactersMathematical from '#ckeditor/ckeditor5-special-characters/src/specialcharactersmathematical.js';
import SpecialCharactersText from '#ckeditor/ckeditor5-special-characters/src/specialcharacterstext.js';
import Strikethrough from '#ckeditor/ckeditor5-basic-styles/src/strikethrough.js';
import Subscript from '#ckeditor/ckeditor5-basic-styles/src/subscript.js';
import Superscript from '#ckeditor/ckeditor5-basic-styles/src/superscript.js';
import Table from '#ckeditor/ckeditor5-table/src/table.js';
import TableCellProperties from '#ckeditor/ckeditor5-table/src/tablecellproperties';
import TableProperties from '#ckeditor/ckeditor5-table/src/tableproperties';
import TableToolbar from '#ckeditor/ckeditor5-table/src/tabletoolbar.js';
import Title from '#ckeditor/ckeditor5-heading/src/title.js';
import TodoList from '#ckeditor/ckeditor5-list/src/todolist';
import Underline from '#ckeditor/ckeditor5-basic-styles/src/underline.js';
import UploadAdapter from '#ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter';
export default class AdvancedEditor extends ClassicEditorBase {}
AdvancedEditor.builtinPlugins = [
Essentials,
UploadAdapter,
Alignment,
Autoformat,
Bold,
Italic,
BlockQuote,
CKFinder,
CKFinderUploadAdapter,
EasyImage,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
HorizontalLine,
Image,
ImageCaption,
ImageResize,
ImageStyle,
ImageToolbar,
ImageUpload,
Indent,
IndentBlock,
Link,
List,
MediaEmbed,
MediaEmbedToolbar,
PageBreak,
Paragraph,
PasteFromOffice,
SimpleUploadAdapterStrapi,
SpecialCharacters,
SpecialCharactersEssentials,
SpecialCharactersArrows,
SpecialCharactersCurrency,
SpecialCharactersLatin,
SpecialCharactersMathematical,
SpecialCharactersText,
Strikethrough,
Subscript,
Superscript,
Table,
TableCellProperties,
TableProperties,
TableToolbar,
Title,
TodoList,
Underline
];
AdvancedEditor.defaultConfig = {
// ...many configurations here
language: 'en'
};
I ran the "npm run build" command and then copied the generated file (with translations folder) to the ./extensions/content-manager/admin/src/components/CKEditor folder and this is how I used it in the index.js file:
import React from 'react';
import PropTypes from 'prop-types';
import CKEditor from '#ckeditor/ckeditor5-react';
import styled from 'styled-components';
import { auth } from 'strapi-helper-plugin';
import AdvancedEditor from './ckeditor.js';
const Wrapper = styled.div`
.ck-editor__main {
min-height: 220px;
> div {
min-height: 220px;
}
}
`;
const Editor = ({ onChange, name, value }) => {
const jwtToken = auth.getToken();
return (
<Wrapper>
<CKEditor
editor={AdvancedEditor}
data={value}
onChange={(event, editor) => {
const data = editor.getData();
onChange({ target: { name, value: data } });
}}
config={{
simpleUpload: {
uploadUrl: `${strapi.backendURL}/upload`,
headers: {
Authorization: "Bearer " + jwtToken
}
}
}}
/>
</Wrapper>
);
};
Editor.propTypes = {
onChange: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
};
export default Editor
Now already in IDE (Webstorm) I receive a Duplicated code fragment warning. Build passed correctly though. But when I go into Admin Panel on the browser I see this error message:
CKEditorError: ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated.
I did follow their instructions, deleted the node_modules folder and installed everything again, but still getting the same error.
Any ideas what is wrong here?
OK, finally figured it out. The problem was in all the plugins with version 18.0.0
I guess they were the ones duplicating some modules. Once downgraded to version 15.0.0 - it all worked as it should!
Here's a link to GitHub repo
And to npm package

Could not find a declaration file for module 'material-ui/styles/MuiThemeProvider'?

I'm trying to use the react material-ui theme having installed it from npm, I get the following errors when I include 'import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";' in boot-client.tsx:
TS7016: Could not find a declaration file for module
'material-ui/styles/MuiThemeProvider'.
'W:/web/WebFront/node_modules/material-ui/styles/MuiThemeProvider.js'
implicitly has an 'any' type. Try npm install
#types/material-ui/styles/MuiThemeProvider if it exists or add a new
declaration (.d.ts) file containing declare module
'material-ui/styles/MuiThemeProvider';
I've tried both suggestions to no avail including running the command: npm install -D #types/material-ui.
My #types folder in node_modules exists with the relevant types.
Here is the code where I'm trying to use it:
import './css/site.css';
import 'bootstrap';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { createBrowserHistory } from 'history';
import configureStore from './configureStore';
import { ApplicationState } from './store';
import * as RoutesModule from './routes';
let routes = RoutesModule.routes;
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
// Create browser history to use in the Redux store
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
const history = createBrowserHistory({ basename: baseUrl });
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = (window as any).initialReduxState as ApplicationState;
const store = configureStore(history, initialState);
function renderApp() {
// This code starts up the React app when it runs in a browser. It sets up the routing configuration
// and injects the app into a DOM element.
ReactDOM.render(
,
document.getElementById('react-app')
);
}
renderApp();
// Allow Hot Module Replacement
if (module.hot) {
module.hot.accept('./routes', () => {
routes = require<typeof RoutesModule>('./routes').routes;
renderApp();
});
}
Ok I figured it out, in tsconfig.json under 'compilerOptions' visual-studio by default had its types set to ["webpack-env"], I needed to add "material-ui" to it or optionally just remove it: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
Use the default import from the same path.
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
The solution that worked for me which is med's answer above which I explain in more detail below.
Open the tsconfig.json file. Add "types":"material-ui", within "compilerOptions": {}
as in
"compilerOptions": {"types":"material-ui"}

angular2 and nativescript does not work - assertion failed: 15G1004 14A345: libxpc.dylib

I am been having a terrible time getting nativescript to work with angular 2 with the official release. I am zero issues with good ole faction web angular but native script is a different story. NativeScript why will my hello world work? I see nothing.
Thanks
Home:
import {Component} from "#angular/core";
import { Router } from "#angular/router";
#Component({
selector: "home",
template: "hello",
})
export class HomeComponent {
constructor(private router: Router){
}
}
app
import {Component} from "#angular/core";
#Component({
selector: "main",
template: "<page-router-outlet></page-router-outlet>",
})
export class AppComponent {
}
Routes:
import { HomeComponent } from "./pages/home/home.component";
export const routes = [
{ path: "", component: HomeComponent }
];
export const navigatableComponents = [
HomeComponent
];
Modules:
import { NgModule } from "#angular/core";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { NativeScriptHttpModule } from "nativescript-angular/http";
import { NativeScriptModule } from "nativescript-angular/platform";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppComponent } from "./app.component";
import { HomeComponent } from "./pages/home/home.component";
import { routes, navigatableComponents } from "./app.routes";
#NgModule({
imports: [
NativeScriptModule,
NativeScriptFormsModule,
NativeScriptHttpModule,
NativeScriptRouterModule,
NativeScriptRouterModule.forRoot(routes)
],
declarations: [AppComponent,
...navigatableComponents ],
bootstrap: [AppComponent]
})
export class AppModule {}
Executing before-prepare hook from /Users/Documents/frontend/bootops-mobile-v1/hooks/before-prepare/nativescript-dev-typescript.js
Project successfully prepared (ios)
Transferring project files...
Successfully transferred all files.
Applying changes...
Sep 17 23:05:18 Davids-iMac com.apple.CoreSimulator.SimDevice.D28D29C3-07B6-4B60-B4B0-711475C505DE.launchd_sim[19187] (UIKitApplication:org.nativescript.bootopsmobilev1[0x7351][20309]): Service exited due to Terminated: 15
Successfully synced application org.nativescript.bootopsmobilev1 on device D28D29C3-07B6-4B60-B4B0-711475C505DE.
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: objc[20349]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x124c81910) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x124aab210). One of the two will be used. Which one is undefined.
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: assertion failed: 15G1004 14A345: libxpc.dylib + 62597 [37A9DF49-35C1-3D93-B854-B35CACF0100F]: 0x7d
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: CONSOLE LOG file:///app/tns_modules/#angular/core/bundles/core.umd.js:210:20: Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
Everything in your code snippets looks good except the part with the HomeComponent template, that Component declaration should look like this:
#Component({
selector: "home",
template: `<Label text="hello"></Label>`,
})
export class HomeComponent {
constructor(private router: Router){
}
}
The reason behind this is the fact that in NativeScript there is not webview it is all native components. So in order for your "hello" text to be rendered you need to use the NativeScript Label. This is all true for NativeScript + Angular 2. Your code snippets work correctly on Angular 2 web because the web browser knows how to render that text, on the other hand NativeScripts Angular 2 renderer does not know how to render a text directly because on iOS and Android there is not such rendering and you need to tell it how via the Label tag.
In the index.html, you have to put <selector-for-the-page></selector-for-the-page> You might have different selector.

Resources