i18next dosen't change language at nextjs app - localization

I'm trying to use i18next for localtization, it works well as it translates english text to arabic {t("title")} ==> مرحبا.
But when i try to change language to english with
const { t, i18n } = useTranslation()
i18n.changeLanguage('en')
it dosen't change.
How to fix this.
I got that error at server vscode terimanl react-i18next:: You will need to pass in an i18next instance by using initReactI18next

I found the solution at nextjs Docs.
It seems changing locales at nextjs not the same as reactjs, with invoking i18n.changeLanguage('en').
But instead use.
<Link href="/fr/another" locale="en">
<a>To /fr/another</a>
</Link>
Will do the job.
more information: https://nextjs.org/docs/advanced-features/i18n-routing

Related

Twitter Card Images not working on Gatsby app

I'm working on a Gatsby app with Netlify CMS (and hosted on Netlify). Trying to get the metadata working so that Twitter cards display correctly with images.
The metadata is generally all right, but the images aren't showing on the Twitter validator or if I try to post to Twitter. The problem is clearly the images themselves, which are hosted on the site using Gatsby and Gatsby Image Sharp to render.
In fact, the validator seems to show no fundamental issues. Simply, the image doesn't show up:
Example relevant metadata:
<meta name="twitter:url" content="https://example.com/" data-react-helmet="true">
<meta name="twitter:image" content="https://example.com/static/12345/c5b20/blah.jpg" data-react-helmet="true">
<meta data-react-helmet="true" name="twitter:title" content="Site title">
<meta data-react-helmet="true" name="twitter:card" content="summary_large_image">
I know the images the issue, because if I replace my image URL (which is the full image URL) with an external URL, it works fine, showing the full card with image.
Any idea what could be causing this? I'm sizing the image down so it loads quickly, and it seems to load just fine directly (eg). (I mean, is there something weird/off about that image?)
NOTE: In a previous version of this question, I referenced Cloudinary and Uploadcare, but have since removed those two in a branch to simplify the problem. (They seem to have been unecessary holdovers from the starter app I used.) You can now see an example page for that branch here and the associated image in the twitter:image tag here. I feed this pre-processed/shrunk image into the header using React Helmet (and Gatsby React Helmet) and using the following code in my GraphQL call to get the image associated with the blogpost in that particular, smaller format:
featuredimage {
childImageSharp {
fixed(width: 480, quality: 75) {
src
}
}
Second Note/thought: Should I be worried about the fact that the pages in production seem to be re-rendering on every reload? Isn't SSR supposed to ensure that doesn't happen? I tested this by including a call to Math.random(), hidden, in the page. You can see the result by running document.getElementsByClassName('document')[0].children[0].innerText, and note that it produces a different number on each page reload. This implies to me that the whole page is being re-rendered by the client. Isn't that wrong? Why would that be happening? Might that relate to some sort of client processing of the images on each request, which might be screwing up the Twitter cards?
Third update: I put together a simpler reproduction here. It's based off of this starter template, with Uploadcare/Cloudinary removed and Twitter card metadata added to the header. Other than that, and removing unnecessary pages, I didn't make any other changes. I used this starter for a repro rather than a vanilla starter app, because I'm unsure whether the issue is caused by the interaction of Netlify CMS and the Gatsby Sharp Image plugin. I might try to put together a second reproduction. For now, the code for this repo is here, and the pages that should show Twitter cards are the blog posts, such as this one.
ACTUALLY, it seems that a super basic reproduction, with Gatsby 3 and no Netlify CMS or anything, has the same issue. Here's the minimal reproduction, with the image taken from src/images using an allImageSharp query and inserted into the metadata for each page. Code here.
FINAL UPDATE
Based on Derek's answer below, I removed the #reach/router stuff, and got the site URL from Netlify build env variables. It appeared that #reach/router only gave this information when JS was running, which excluded the Twitterbot, resulting in an undefined base URL, which broke the Twitter image. Including the URL from Netlify (using process.env.URL in the Gatsby config and pulling that in through a siteMetadata query) fixed the problem!
Update:
I think I might have found the issue. When opening the minimal production with script disabled, the url for twitter:image is invalid:
<meta data-react-helmet="true" name="twitter:image" content="undefined/static/03475800ca60d2a62669c6ad87f5fda0/58026/energy.jpg">
So for some reasons, during build, the hostname is missing, but when JS kicks in, it appears (Might have something to do with the way you get the hostname). Twitter crawlers probably does not have JS enabled & couldn't fetch the image.
Make sure your opengraph images are absolute urls with https:// or http:// protocols. I checked your example link & saw that it was a relative link (/static/etc.)
For Twitter, it seems to demand social cards to be 2:1
Images for this Card support an aspect ratio of 2:1 with minimum dimensions of 300x157 or maximum of 4096x4096 pixels.
https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary-card-with-large-image
If you're using the latest Gatsby image plugin, you can use aspectRatio to crop the image.
Also note that you can skip the twitter:image tag, if your og:image has already satisfied Twitter's card requirement.
SSR does not mean to never run JS in the client, React will render your page on the client side regardless of SSR.
This was solved here: https://github.com/gatsbyjs/gatsby/discussions/32100.
"location and thus origin is not available during gatsby build and thus the generated HTML has undefined there."
I got it working by changing the way I create the image URL inside seo.js from this:
let origin = "";
if (typeof window !== "undefined") {
origin = window.location.origin;
}
const image = origin + imageSrc;
to this:
const imageSrc = thumbnail && thumbnail.childImageSharp.fixed.src;
const image = site.siteMetadata?.siteUrl + imageSrc;
You need to use siteUrl from siteMetadata.
Below is my pageQuery from inside blog-post.js:
export const pageQuery = graphql`
query BlogPostBySlug(
$id: String!
$previousPostId: String
$nextPostId: String
) {
site {
siteMetadata {
title
siteUrl
}
}
markdownRemark(id: { eq: $id }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
thumbnail {
childImageSharp {
fixed(width: 1200) {
...GatsbyImageSharpFixed
}
}
}
}
}
}
`

How to use i18n (localization) in Parse Server, inside a cloud code function?

I am trying to localize a push notification text while inside a Parse Cloud function and after many tries I was not able to have working solution. Is there a way to localized text inside a Parse Server cloud function?
So, for anyone looking for a solution, I used the following library: i18n-node.
Then in the cloud code (I am using Typescript):
import i18n from 'i18n';
//... other imports
i18n.configure({
locales:['en', 'it'],
directory: __dirname + '/locales'
});
And then inside a cloud function is possible to run:
i18n.__({phrase: "Hey, well done!", locale: locale}
Where locale can come from the request or, in my case, from the user's device language preference.
I had the same problem, and solve it with UTF-8 encoding before sending the notification.
npm package: UTF8
Usage:
var utf8 = require("utf8");
// encode before sending the text
text = utf8.encode(text);

Nexmo VoiceXML not working in language other than en-US

I have a running VoiceXML application that works ok in Nexmo. If I set any language other than en-US the calls want get answered. I just change en xml:lang as in:
<vxml application="/dialogue/root/50b9bab0-9ce8-4d7a-9389-09f06aa8f9ee" version="2.1" xml:lang="es-es">
I have tried in the vxml above and also in the prompt tag. Any language like es-es, es-ES... even en-UK will make my vxml stop working in Nexmo.
I am sure script is OK as I can change en-US female and male voice with en-us-male and en-us-female. That works.
Am I missing something?
(I don't think it makes a difference but I use the great Rivr java library to generated vxml)
for me "fr-ca" doesnt work but "fr-ca-female" does work

Use local json file with Cordova/ionic/Angular. Works in browser, but not on device?

I'm attempting to use a JSON object living in a data.json file to be the dataset for a quick prototype I'm working on. This lives in a my_project/www/data/ directory. I have an Angular service that goes and grabs the data within this file using $http, does some stuff to it, and then it's used throughout my app.
I'm using Cordova and Ionic. When using ionic serve on my computer, everything looks perfect in the browser. However, when using ionic view (http://view.ionic.io/) and opening the app on my iPad, I see a:
{"data":null,"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":"../data/items.json","headers":{"Accept":"application/json,test/plain,*/*}},"statusText":""}
for a response. I would think that if it were a relative URL issue, that it would also not work in the browser, but that is not the case.
Here's what I'm doing:
config.xml has this line:
<access origin="*" subdomains="true"/>
My service that preforms the simple request is doing:
return $http.get("../data/data.json").then(function (response) {
return response.data;
});
And finally, in my controller, I ask for the service to preform the request:
myService.goGetData().then(onComplete, onError);
In my browser, onComplete() is invoked and on the iPad, onError() is invoked.
Any guidance?
On your local developer machine you're actually running a webserver when you run ionic serve. So a path like ../../data.json will work because it is totally valid in the context of the webserver that has complete filesystem access.
If, however, you try to do the same thing on your device, you're probably going to run into an issue because the device has security policies in place that don't allow ajax to traverse up outside of the root. It is not a dynamic webserver so it can't load files up the tree. Instead you'd use something like the cordova file plugin to grab the file contents from the filesystem. If you prefer, you can use ngCordova to make interacting with the plugin a bit less painful.
I am 99% sure this is what is happening but you can test my theory by pointing your $http call to some dummy .json data hosted on a publicly available server to see if it works. Here is some dummy json data.
Just gonna leave this here because I had the same problem as the original question author. Simply removing any starting slashes from the json file path in the $http.get function solved this problem for me, now loading the json data works both in the browser emulator and on my android device. The root of the $http call url seems to always be the index.html folder no matter where your controller or service is located. So use a path relative from that folder and it should work. like $http.get("data/data.json")
So this is an example json file. save it as data.json
[
{
"Name" : "Sabba",
"City" : "London",
"Country" : "UK"
},
{
"Name" : "Tom",
"City" : "NY",
"Country" : "USA"
}
]
And this this is what a example controller looks like
var app = angular.module('myApp', ['ionic']);
app.controller('ExhibitionTabCtrl', ['$scope', '$http', function($scope,$http) {
$http.get("your/path/from/index/data.json")
.success(function (response)
{
$scope.names = response;
});
}]);
Then in your template make sure you are you are referencing your controller.
<ion-content class="padding" ng-controller="ExhibitionTabCtrl">
You should then be able to use the a expression to get the data
{{ names }}
Hope this helps :)
I was also looking for this and found this question, since there is no real answer to the problem I kept my search on the Internet and found this answer at the Ionic Forum from ozexpert:
var url = "";
if(ionic.Platform.isAndroid()){
url = "/android_asset/www/";
}
I've used it to load a 3D model and its textures.
update: ionic 2 beta (version date 10 Aug 2016)
You must add prefix to local url like this: prefix + 'your/local/resource'.
prefix by platform:
ios = '../www/'
android = '../www/'
browser = ''
we can create an urlResolver provider to do this job.
notice: only change url in *.ts code to access local resource, don's do this with remote url or in html code.
Have fun and good luck with beta version.
An Starter Ioner
It is possible to access local resources using $http.get.
If the json file is located in www/js/data.json. You can access using
js/data.json
Do not use ../js/data.json. Using that only works in the local browser. Use js/data.json will work on both local browser and iOS device for Cordova.

Can the document.location.protocol value be changed in a WinRT webview?

I'm currently having an issue with the WebView control used in a Universal WinRT app (Windows 8.1/Windows Phone 8.1).
I currently load the following piece of JavaScript into the WebView using the NatigateToString method:
<html>
<head>
<base href='MY_BASE_URL'>
</head>
<body>
<script>
var idcomments_acct = 'MY_ACC_ID';
var idcomments_post_id='POST_ID';
var idcomments_post_url='POST_URL';
</script>
<span id='IDCommentsPostTitle' style='display:none'></span>
<script type='text/javascript' src='http://www.intensedebate.com/js/genericCommentWrapperV2.js'></script>
</body>
</html>
This is the piece of code for the IntenseDebate generic install that can be found here.
The issue is with this line of code in the referenced IntenseDebate code:
load_js(document.location.protocol+"//connect.facebook.net/en_US/all.js")
This piece of code fails because document.location.protocol is set to about: in the WebView, leading to a 404 error on this call.
On the Android/iOS webviews simply setting the base URI to a http: or https: based address using their loadDataWithBaseUrl methods worked fine, but the WinRT WebView is missing a similar method. And setting the Base url in the HTML itself (like shown in the piece of code above) does work for resolving image url's and sortlike, but this method doens't change the document.location values.
Since I can't modify the referenced JS file and putting the above piece of HTML on a server isn't an option in this apps usecase, is there any way you can force the document.location.protocol to be a certain value in the WinRT webview? Or is there any other way to get this bit of HTML to work in a webview?
There isn't a direct way to do this. WebView doesn't provide any interface to override the document.location . If branching off of the protocol is a common pattern then this may be a good feature to request on http://wpdev.uservoice.com .
I'm not familiar enough with HTML/JavaScript best practices to say for sure, but most of the references I find searching for document.location.protocol warn against assuming that the protocol will always be http: or https. This may be something that IntenseDebate should fix.
That said, you may be able to get past this by injecting code into your page which finds the problem location in the DOM and changing it live. You can't change just the protocol, but you may be able to find where it is referenced and change that there. I assume it gets loaded into the commentScript.src from genericCommentWrapper2.php referenced in genericCommentWrapper2.cs and then added to the document's head.

Resources