#nuxtjs/i18n locales changing after refresh - javascript

I have an application where I try to put the language management but I face a difficulty.
I'm on the latest version of #nuxtjs/i18n. When I change language, my URl changes, my labels change, everything is fine. When I refresh my page, however, the system reverts to the old language.
Here is my conf:
[
'#nuxtjs/i18n',
{
locales,
defaultLocale,
lazy: true,
langDir: 'locales/',
vueI18n: {
fallbackLocale: defaultLocale,
},
},
],
['~/.build/merge-and-compare-locales.js', { defaultLocale }],
export const locales = [
{
code: 'en',
file: 'en.json',
},
{
code: 'fr',
file: 'fr.json',
},
]
export const defaultLocale = 'fr'
What more do I need to do to make it keep the language before refresh?
I specify that I use this method to change the language:
changeLocale(code: string) {
this.$i18n.setLocale(code)
},
Locally it works fine. On the other hand on any other environment it does not work, the refresh makes return to the default language

i have same problem and it's come from ssr...
inside your store/index you should have a nsi (nuxt server init) function
something like this.
/** initial the store when user fetch the web app */
async nuxtServerInit(ssrContext: Context) {
if (this.$i18n.locale==='ar') {
ssrContext.redirect("/ar");
}
else if (this.$i18n.locale === 'fa')
{
ssrContext.redirect('/')
}
}

Related

Conditionally set anonymize_ip in Gatsby

I am trying to implement tracking acceptance on a Gatsby site using gatsby-plugin-google-gtag and a custom cookie prompt component.
Currnetly the tracking code is setup and working and the cookie prompt component is conditionally rendering depending if the user has previously made their choice regarding tracking. Where things are failing is trying to conditionally set anonymize_ip based on the users choice. I have tried to set true/false based on a ternary statement in gatsby-config.js, but this seems to error login issues in terminal relating to GraphQL (not linked).
anonymize_ip: document.cookie.match(/^(.*;)?\s*ga-disabled\s*=\s*[^;]+(.*)?$/) ? true : false, // If cookie exists, set value to true
Does anyone know the best way to achieve this?
Thanks
Cookie Prompt
import React from "react";
import { setCookie } from "../../assets/js/utils/cookies";
const CookiesPrompt = () => {
const gaOptout = () => {
setCookie('ga-disabled', true, 30);
}
const gaAccept = () => {
setCookie('ga-hide-prompt', true, 30);
}
return (
<div className="cookies-prompt">
<div className="cookies-prompt__wrap">
<div className="cookies-prompt__title">This website uses cookies</div>
<button onClick={() => gaOptout()} className="cookies-prompt__link button--non">I wish to opt-out</button>
</div>
<button onClick={() => gaAccept()} className="cookies-prompt__button button button--primary">Accept</button>
</div>
);
};
export default CookiesPrompt;
Gatsby-config.js
plugins: [
"gatsby-plugin-sass", "gatsby-plugin-react-helmet", "gatsby-transformer-json", "gatsby-plugin-image", "gatsby-plugin-sharp", "gatsby-transformer-sharp",
{
resolve: `gatsby-plugin-google-gtag`,
options: {
// You can add multiple tracking ids and a pageview event will be fired for all of them.
trackingIds: [
'G-xxxxxxx', // Google Analytics / GA
],
// This object gets passed directly to the gtag config command
// This config will be shared across all trackingIds
gtagConfig: {
// optimize_id: 'OPT_CONTAINER_ID',
anonymize_ip: document.cookie.match(/^(.*;)?\s*ga-disabled\s*=\s*[^;]+(.*)?$/) ? true : false, // If cookie exists, set value to true
cookie_expires: 0,
},
// This object is used for configuration specific to this plugin
pluginConfig: {
// Puts tracking script in the head instead of the body
head: false,
// Setting this parameter is also optional
respectDNT: true,
// Avoids sending pageview hits from custom paths
exclude: ['/preview/**', '/do-not-track/me/too/'],
},
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'data', // Identifier. Will then be queried as `dataJson`
path: './src/assets/data', // Source folder containing the JSON files
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'projectImages', // Identifier. Will then be queried as `projectImagesJson' ?
path: './public/static/projects', // Source folder containing the JSON files
},
},
]
gatsby-config.js configurations are set on build-time, not on runtime, so there's no way that you can listen document in that environment/file on-demand.
However, you can use the anonymize IP based on user choice (onClick) by triggering the gaOptout() function:
<div onClick={gaOptout}>Deactivate Google Tracking</a>
Where gaOptout:
function gaOptout() {
;(document.cookie =
disableStr + "=true; expires=Thu, 31 Dec 2099 23:59:59 UTC;path=/"),
(window[disableStr] = !0)
}
var gaProperty = "UA-XXXXXXXX-X",
disableStr = "ga-disable-" + gaProperty
document.cookie.indexOf(disableStr + "=true") > -1 && (window[disableStr] = !0)

Formatting cells with the Google Sheets API (v4)

I'm using the Google Sheets API (v4) to create/update spreadsheets programmatically and have run into the following issue:
As per the documentation (https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/cells#CellFormat), I'm setting the number format to CURRENCY; this will correctly display the number as a numeric value with a ¥ sign at the front (Japanese locale). However, it does not seem to actually select the "Currency" option on the formats dropdown, and more importantly, does NOT reflect the specified format when downloading the spreadsheet (e.g. as an .xlsx file).
This is different from selecting the 'Currency' option manually (via the UI), in which case values are correctly displayed once downloaded.
Here's the relevant section of code:
import { google, sheets_v4 } from 'googleapis';
const sheetsApi = google.sheets({
version: 'v4',
auth: await this.getAuthClient(),
});
await sheetsApi.spreadsheets
.batchUpdate({
spreadsheetId: resource,
requestBody: {
requests: [
{
updateSpreadsheetProperties: {
fields: 'locale',
properties: {
locale: 'ja',
},
},
},
...,
{
repeatCell: {
fields: 'userEnteredFormat.numberFormat',
cell: {
userEnteredFormat: {
numberFormat: { type: 'CURRENCY' },
},
},
},
},
],
},
})
.catch((error) => {
console.log(error);
});
I've also tried settings the pattern (tried few different ones), but haven't been able to actually set the cell format, despite the value being displayed as such.
Probably a simple mistake, but I've been stuck on this for a while.. any help would be greatly appreciated!
In that case, I thought that the property of pattern might be required to be set. So in this case, how about modifying your request of repeatCell as follows?
Modified request:
{
"repeatCell": {
"range": {,,,}, // Please set range.
"cell": {
"userEnteredFormat": {
"numberFormat": {
"type": "CURRENCY",
"pattern": "[$¥-411]#,##0.00" // <--- Added
}
}
},
"fields": "userEnteredFormat.numberFormat" // or "fields": "userEnteredFormat"
}
}
Note:
In my environment, when above modified request is used for the batchUpdate method, I could confirm that "Currency" was checked.
References:
RepeatCellRequest- NumberFormat

Gatsby i18next plugin No codeFrame could be generated

I'm developing a website with Gatsby and I wanted to implement multi-language support.
So I used the gatsby-plugin-react-i18next plugin.
I followed all the steps, but it doesn't work, once I log into my website this error message shows:
error message
Right now, my code is the next one.
gatsby-config.js
module.exports = {
siteMetadata: {
title: "Space",
},
plugins: [
"gatsby-plugin-postcss",
{
resolve: `gatsby-source-filesystem`,
options: {
name: `locale`,
path: `${__dirname}/locales`
}
},
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`, // name given to `gatsby-source-filesystem` plugin.
languages: [`en`, `es`],
defaultLanguage: `en`,
// if you are using Helmet, you must include siteUrl, and make sure you add http:https
siteUrl: `https://example.com/`,
// you can pass any i18next options
// pass following options to allow message content as a key
},
pages: [
{
matchPath: '/:lang?/blog/:uid',
getLanguageFromPath: true,
excludeLanguages: ['es']
},
{
matchPath: '/preview',
languages: ['en']
}
]
}
],
};
index.js
import * as React from "react"
import { graphql } from "gatsby"
import { useTranslation } from "gatsby-plugin-react-i18next"
export default function IndexPage() {
const { t } = useTranslation();
return (
<h1>{t("Space")}</h1>
)
}
export const query = graphql`
query($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) {
edges {
node {
ns
data
language
}
}
}
}
`;
And of course I have the translation folders project structure
Im trying this plugin on a new blank project, not on my main project, so I don't understand why the plugin fails.
Any thoughts? Thanks in advice!
Edit: I add the translation.json of the two languages
English
Spanish
Your JSONs looks and the implementation too (couldn't be wrong being that simple). So to me, the issue relies on the configuration. Try something simpler such as:
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`,
path: `${__dirname}/locales`,
languages: [`en`, `es`],
defaultLanguage: `en`,
i18nextOptions: {
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
keySeparator: false,
nsSeparator: false,
},
},
},

Vue.js Dynamic Image paths after compiling/runtime

I am having a problem setting dynamic image paths with Vue.js. I am using the Vue-Cli to build the project.
I believe the issue is caused because I am referencing image paths dynamically after runtime. Normally it seems the references to my ./assets/ folder are converted into ./img/ after runtime. Since I am changing the url dynamically after load the paths don't appear to work/load. Country is initially set via a store getters but is then v-modeled from a language select dropdown, where the values correspond the the url suffix.
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
}
},
data() {
return {
country: this.$store.getters.language
}
}
Inspector shows url change is implemented.
Any recommendation on the best solution for this?
Using webpack require context and beforeMount, I was able to store the images in base64 format inside an object. I stored the object and accessed it with a dynamic key. Thanks Max for leading me to the right documentation.
export default {
beforeMount() {
var that = this;
function importAll(r) {
r.keys().forEach((key) => (that.imgCache[key] = r(key)));
}
importAll(require.context("../assets/flags/", true, /\.png$/));
},
computed: {
src() {
var key = `./flag-${this.country}.png`,
url = this.imgCache[key];
return url;
},
},
};
Don't use
data() {
return {
country: this.$store.getters.language
}
}
as it will stop being reactive to store changes. Use computed property
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
},
country() {
return this.$store.getters.language
}
},

How to properly write a vuepress plugin?

I am trying to write a Vuepress plugin to make use of App Level enhancement and install a Vue plugin. But I can't seem to get this to work. Can you please take a look at the code below and see what is wrong?
{.vuepress/config.js}
module.exports = {
plugins: [
require('./builder.plugin.js')
]
}
{.vuepress/builder.plugin.js}
module.exports = (option, ctx) => {
return {
enhanceAppFiles: [{
name: 'builder-plugin',
content: `export default ({ Vue }) => {
Vue.component('b-header', {
name: 'b-header',
template: '<div id="header"><slot /></div>'
})
}`
}]
}
}
{README.md}
# Introduction
<b-header>Test from component</b-header>
The final error I get is:
Unknown custom element: <b-header> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I actually found the answer. The above did not work because I was mixing client site code with runtime code by using a plugin.
The trick was to use enhanceAPP hook.
ref: https://vuepress.vuejs.org/guide/basic-config.html#theme-configuration

Categories

Resources