Vue i18n sometimes warn about missing key - vue.js

In my home component I have the following:
const { location } = useLocation();
const { t, n } = useI18n();
const freeShippingValue = computed(() => {
return n(100, 'currency', location.value);
});
In my BaseMoney component I have:
const { n } = useI18n();
const { location } = useLocation();
const formattedMoney = computed(() => {
return n(amount.value, 'currency', location.value);
});
In Home.js this generates warnings:
[intlify] Not found 'currency' key in 'DE' locale messages.
[intlify] Fall back to number format 'currency' key with 'en-US' locale.
[intlify] Not found 'currency' key in 'en-US' locale messages.
[intlify] Not found 'currency' key in 'en-US' locale messages.
[intlify] Not found 'currency' key in 'en-US' locale messages.
[intlify] Fall back to number format 'currency' key with 'en' locale.
[intlify] Not found 'currency' key in 'en' locale messages.
[intlify] Fall back to number format 'currency' with root locale.
Full code is here
I set up i18n here home is here and BaseMoney is here
Why would I get warnings in one component but not in another?
I can change both Home and BaseMoney to return n(100, 'currency', 'US'); and still get a warning in Home but not in BaseMoney.
When I remove translations for the component the warnings are not there but I don't understand why adding component translations breaks number formatting.

Related

Best way to have a default dynamic value derived from other atom [Recoil]

I am developing an app, which has sidebar menu. I have an atom, which saves the state of the /menu and an atom which saves the last selected menu key (as this key is used for other selectors too) -> for getting specific info for the current selected key.
export const menuItems = atom({
key: "menuItems",
default: ({ get }) => get(baseApi)("/menu"),
}); -> Returns Menu Items
And then I have an atom, which saves the selected menu item key:
export const selectedMenuKey = atom<string>({
key: "selectedMenuKey",
});
I cannot prefix the initial selected menu key as I don't know it in advance. I want the behavior to be following:
If the key is not set (when the app initially runs) set the selectedMenuKey value to be the first item of the menuItems atom value, otherwise be whatever is set last.
What would you say is the best way to achieve this?
I ran into this exact use case. Here is what I ended up doing.
In my 'activeTabState' file, equivalent to your 'selectedMenuKey':
import { atom, selector } from 'recoil';
import formMapState from './formMapState';
const activeTabState = atom({
key: 'activeTabAtom',
default: selector({
key: 'activeTabDefault',
get: ({ get }) => {
const formMap = get(formMapState);
if (!formMap) return null;
const [defaultTab] = Object.keys(formMap);
return defaultTab;
},
}),
});
export default activeTabState;
Then you can update the tab just like any other recoil state:
const FormNavigationTab = (props) => {
const { text, sectionName } = props;
const [activeTab, setActiveTab] = useRecoilState(activeTabState);
return (
<NavigationTab active={activeTab === sectionName} onClick={() => setActiveTab(sectionName)}>
{text}
</NavigationTab>
);
};
One thing to watch out for is that your activeTab value will be null until the menu items are loaded. So based on my use case, I needed to add a safeguard before using it:
const FormPage = () => {
const map = useRecoilValue(formMapState);
const activeTab = useRecoilValue(activeTabState);
// Starts out null if the map hasn't been set yet, since we don't know what the name of the first tab is
if (!activeTab) return null;
const { text, fields, sections } = map[activeTab];
// ... the rest of the component

react native reselect error selector creators except all input

what I do am wrong ?
reselect.js
import { createSelector } from 'reselect';
const createCollection = state => state.createCollection;
export const getCollectionName = createSelector(
createCollection,
(el) => el
);
if I only import the file, then I get this error:
Error: Selector creators expect all input-selectors to be functions, instead received the following types: [undefined]
Must be an import problem, you have no error in the code you provided:
const { createSelector } = Reselect;
const state = {};
const createCollection = state => state.createCollection;
const getCollectionName = createSelector(
createCollection,
(el) => el
);
console.log(getCollectionName(state))
console.log(
'also works:'
,getCollectionName(
{createCollection:'hello world'}
)
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
You should probably log what createCollection is before using it in createSelector.
You should prefix your selectors with select so your future self and other members of your team can recognise the selectors: selectCreateCollection and selectCollectionName

vue-i18n: Wrong date format for e.g. Norwegian

I'm using vue-i18n (version 8.24.2) in my app, and everything works as expected except when rendering dates using locale = nb-NO (Norwegian). Expected format: dd.MM.yyyy. Actual format: MM/dd/yyyy. When switching locale to German, which is using the same date format as Norwegian, correct date format is applied.
This open issue would probably solve my issue:
https://github.com/kazupon/vue-i18n/issues/625
I've spent a couple of hours investigating this issue, but I'm currently stuck, hence any help will be highly appreciated.
My i18n.ts (I left out config for languages not related to this issue)
import Vue from "vue";
import VueI18n from "vue-i18n";
enum Locales {
NO = "nb-NO"
}
const LOCALES = [
{ value: Locales.NO, caption: "Norsk" }
];
import nb_NO from "./locales/nb-NO.json";
export const messages = {
[Locales.NO]: nb_NO
};
const defaultLocale = Locales.NO;
const dateTimeFormats = {
"nb-NO": {
short: {
year: "numeric",
month: "2-digit",
day: "2-digit",
},
long: {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false,
},
},
} as VueI18n.DateTimeFormats;
Vue.use(VueI18n);
// Create VueI18n instance with options
const i18n = new VueI18n({
locale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE || defaultLocale,
fallbackLocale: defaultLocale,
messages,
dateTimeFormats: dateTimeFormats,
silentTranslationWarn: true,
});
const translate = (key: string): string => {
if (!key) {
return "";
}
return i18n.t(key) as string;
};
export { i18n, translate }; //export above method
vue-i18n simply forwards the date localization to Intl.DateTimeFormat(locale).format(date).
It seems the result is only incorrect in Chrome as of v92 (Issue 1233509). This bug is fixed in Chrome Canary v94.
As a workaround, you can modify the vue-i18n instance's _dateTimeFormatters to use the Danish (da) locale's formatter for nb-NO:
const i18n = new VueI18n({/*...*/});
i18n._dateTimeFormatters[Locales.NO + '__short'] =
new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].short);
i18n._dateTimeFormatters[Locales.NO + '__long'] =
new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].long);
demo

Display date from Firestore React native

I try to display the picked event date för my posts from Firestore using moment. Right now it just print The current day, so I display the date but not ont he right way. I get no error message. I have tried to change the timestamp to "dateUpload". but it gives me a print in my Text component "invalid date". Do any have clue of what I can do?
This is how display it my flatlist:
postDate={moment(item.timestamp).format("ll")}
In my redux Action.js
export function fetchFollowingUsersPosts(uid) {
return ((dispatch, getState) => {
firebase.firestore()
.collection("posts")
.doc(uid)
.collection("userPosts")
.orderBy("creation", "asc")
.get()
.then((snapshot) => {
const uid = snapshot.query.EP.path.segments[1];
const user = getState().usersState.users.find(el => el.uid === uid);
const posts = snapshot.docs.map((doc) => {
const { data: firebaseTimestamp, ...rest } = doc.data()
const id = doc.id;
const data = firebaseTimestamp ? moment(firebaseTimestamp.toDate()) : null
return {
...rest,
id,
user,
...data
}
})
//console.log(posts);
dispatch({ type: USERS_POSTS_STATE_CHANGE, posts, uid, })
})
})
}
Image on my database:
Instead of const data = firebaseTimestamp ? moment(firebaseTimestamp.toDate()) : null, try this const data = firebaseTimestamp ? firebaseTimestamp.toDate() : null , so you'll be having a javascript Date object, instead of a Moment object.
Then, you can use it as you did postDate={moment(item.timestamp).format("ll")}, assuming that item.timestamp is the Date object from above

i18n won't translate correctly when inside array or object in React Native

I'm trying to use i18n-js to translate some strings into other languages. If I have my code in normal code, it works. Ex:
//Displays "Something" (no quotes) where I want it
<Text> translate("Something"); </Text>
But if I put it inside an array or object, then call it later, it stops working and shows a missing message instead of the text I want translated. Ex:
const messages = {
something: translate("Something"),
// other translations...
}
// later on
// Displays "[missing "en.Something" translation]" (no quotes) where I want it
<Text> messages.something </Text>
The following is my code for my translate function, as well as the config for i18n. I'm using lodash-memoize, but that is unrelated to the issue. I've already checked that the text being passed to i18n.t() is the same (including type) no matter if it's in normal code or in the array, but it still doesn't return the correct thing. I have some error checking written up to avoid getting the missing message on screen, but that still doesn't fix the issue that it can't find the translation.
export const translationGetters = ({
en: () => require('./translations/en.json'),
es: () => require('./translations/es.json')
});
export const translate = memoize(
(key, config) => {
text = i18n.t(key, config)
return text
},
(key, config) => (config ? key + JSON.stringify(config) : key)
);
export const setI18nConfig = () => {
// fallback if no available language fits
const fallback = { languageTag: "en", isRTL: false };
const { languageTag, isRTL } =
RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
fallback;
// clear translation cache
translate.cache.clear();
// update layout direction
I18nManager.forceRTL(isRTL);
// set i18n-js config
i18n.translations = { [languageTag]: translationGetters[languageTag]() };
i18n.locale = languageTag;
};
I have no idea where to go on this. Any advice would be appreciated!
Same problem here, workaround is to return array/object from inside a function:
Don't work
export const translations = [i18.t('path')]
Works
export function getTranslations() {
const translations = [i18.t('path')]
return translations
}