This question already has answers here:
How to setup i18n translated URL routes in Next.js?
(2 answers)
Closed 6 months ago.
I'm really happy to see i18n going into Next.js core with Next.js 10.
However, I'm wondering if and how we can use i18n to translate page names (urls?).
For example, let's say I have a contact page under mypage.de/kontakt (for default German language).
With Next.js 10 configured, Next.js automatically creates the route mypage.de/en/kontakt, which is fine so far, but how can we translate the page name as well? Instead of /kontakt, I'd like to have /contact.
Is or will this be possible with Next.js 10 out of the box?
Does it require additional libraries? What will be the right way to do this in 2021?
Thank you very much!
Imagine you have only one file named src/pages/contact.tsx. There are 2 scenarios.
User is hitting "foobar/contact" URL => you can use i18n redirection to redirect to "foobar/de/contact". Then client side you can use the browser API to change the URL (see related question).
User is hitting "foobar/de/kontact" => since your page is named "contact" and not "kontact", that's a problem, because this page doesn't exist. You'll hit a 404 as is. Here you need a rewrite as stated by #enoch comment on your question. You'll want to rewrite "kontact", "contactez-nous", "contactar"... to "contact" route.
Hopefully, Next.js rewrite feature is very powerful, and allow some slight decoupling between the actual route path and the URL seen by the user. And you can also alter the URL directly in JS.
A third way is to use URL rewriting server-side, but for that at the time of writing (Next 11) it can only be handled ad the host level, so it depends where you upload the app.
Related
The app
The application was made using ReactJS, React Router Dom, Styled Components and Redux ducks.
The backend we consume is also made by us using Amazon Amplify and GraphQL.
The goal
We need to define the meta tags of one of the application pages so that it is possible to share personalized links to users
in social networks using OpenGraphic meta tags and the like.
The problem
The project was made in ReactJS and ReactJS has only one HTML page as root (/public/index.html), in this way, everything is generated with Javascript in a root tag, and when it arrives in the browser it is transpiled, as we already know. The problem is that the crawlers responsible for understanding the meta tags are not able to understand Javascript and end up not finding the dynamic data that I am defining on the page that I need to share the link on. They understand that there is one html file and only.
Attempts to resolve the issue
1) Define the meta tags in the /public/index.html file itself
This solution doesn't work because the data we are using is dynamic and the index.html file is a static file
2) Using react-helmet
The solution allows meta tags to be defined, but as already mentioned, crawlers don't understand JS. So, despite being on the page, the meta tags do not appear when sharing the link.
3) Using some SSR technology
This is a possible solution, but we were unable to integrate any SSR Framework into React. And it is not feasible to change the base technology of the project. We can't just switch from React to Next, for example, as the project is already complete.
4) Using a small server made with express.js along with the React application to replace the meta tags in index.html with string.replace() simulating something like an SSR
This solution works, but it causes two requests to be made every time the page is accessed, once by express.js and once on the front-end side by React. Due to the number of requests increasing, this solution was discarded. But if necessary, you can do it. In this case it is also necessary to check if Amplify can keep the application and the small server running in the same project.
5) Using react-snap with react-helmet
React-snap allows you to create html snapshots of the pages of a React project based on their routes and links, this added to react-helmet generates a perfect solution for links to be treated well by web crawlers when they are shared. But the solution doesn't work with dynamic routes. For example, /your-route/:id is a dynamic route that expects an id to be fully defined. React-snap gets lost when trying to create a snapshot of a route that only exists when the id is set. Unfortunately, this solution doesn't work.
These were the solutions we used to try to solve the problem, but it was not possible yet. Probably attempt 4 would be the most ideal to solve the problem. But we are looking for the best way that will not generate reworks and future problems. If someone knows a better way to do that, would help us a lot!
I use digital ocean space and CDN to host a React SPA. When hitting with a browser the url [host]/index.html it works fine. However hitting [host]/index.html/customers/one or any other subpaths, returns a 404. Currently, any reload on any subpath returns that 404. Last, I use terraform to update the SPA artifacts on DO spaces and I have tried to add a website_redirect="/index.html" to all the bucket objects (js, html and css) but with no success (more info if necessary here). And to be completely honest I am not sure I understand that option in the terraform digitalocean provider. I might be using it completely wrong.
Now, I have seen that question in multiple places but never with a clear answer.
Here is one on digitalocean community (https://www.digitalocean.com/community/questions/is-it-possible-to-send-a-301-redirect-for-bucket-objects) where no answer is provided but the issue seems to be similar.
There is a similar question on SO without an approved answer Redirect wrong URL/path DigitalOcean Spaces
This is a DO idea that is somewhat related https://ideas.digitalocean.com/ideas/DO-I-318
Is there a way to achieve the mentioned goal of loading index.html for every route with DO space + CDN and let the app parse the rest of the path to display the right component subtree of the react app?
I'm deciding whether it's safe to develop my client-facing app in AngularJS using pushState.
I've read that when using pushState in an AngularJS app, we don't need to worry about Googlebot because it can now execute enough JS to produce an HTML snippet for itself. But then I wonder about Bing, Facebook and other bots and scrapers. The tutorials I've seen for making AngularJS SEO-friendly all deal with apps that use hashbangs (#!). These don't apply to me since I'm not using hashbangs.
Does anyone have insight into this problem? What are some methods for ensuring an AngularJS app that uses pushState is SEO-friendly and Social-scraper-friendly? If you use a service like Seo4Ajax or prerender.io I'd appreciate your thoughts on it.
Note: As I understand it, when developing single page apps in the last couple of years it has been necessary to send HTML snippets to SEO crawlers. This was accomplished by using hashbangs and a meta tag that let Google, Bing and Facebook know that it needed to replace the bang (!) with an _escaped_string when making a request. On the server you'd listed for requests with _escaped_string and deliver the appropriate HTML snippet using a tool to generate HTML snippets like phantomJS.
Now that we have pushState, I don't see how we indicate to javascript-less bots what part of the URL to rewrite with an _escaped_string or even if it's necessary. I'm having trouble finding any information beyond "you're site will be okay with google ;)".
Here are some other SO questions that are similar but have gone unanswered.
Angularjs vs SEO vs pushState
.htaccess for SEO bots crawling single page applications without hashbangs
Here's a solution I posted in that question and am considering for myself in case I want to send HTML snippets to bots. This would be a solution for a Symfony2 backend:
Use prerender or another service to generate static snippets of all your pages. Store them somewhere accessible by your router.
In your Symfony2 routing file, create a route that matches your SPA. I have a test SPA running at localhost.com/ng-test/, so my route would look like this:
# Adding a trailing / to this route breaks it. Not sure why.
# This is also not formatting correctly in StackOverflow. This is yaml.
NgTestReroute:
----path: /ng-test/{one}/{two}/{three}/{four}
----defaults:
--------_controller: DriverSideSiteBundle:NgTest:ngTestReroute
--------'one': null
--------'two': null
--------'three': null
--------'four': null
----methods: [GET]
In your Symfony2 controller, check user-agent to see if it's googlebot or bingbot. You should be able to do this with the code below, and then use this list to target the bots you're interested in (http://www.searchenginedictionary.com/spider-names.shtml)...
if(strstr(strtolower($_SERVER['HTTP_USER_AGENT']), "googlebot"))
{
// what to do
}
If your controller finds a match to a bot, send it the HTML snippet. Otherwise, as in the case with my AngularJS app, just send the user to the index page and Angular will correctly do the rest.
Supposedly, Bing also supports pushState. For Facebook, make sure your website takes advantage of Open Graph META tags.
in order to make nice urls, I decide to remove the # from my ulrs using the tip from the following question Removing the fragment identifier from AngularJS urls (# symbol) Now, I realized that my urls are not working if I try a direct access to them. from the given example in the related question if put the url below directly in the browser http://localhost/phones
I'll get a 404.
Any idea how to solve this?
You need to write server side code that will generate the page that you were previously depending on the client-side JavaScript to generate.
This will then be the initial view for that URL.
If the client supports JavaScript (and the JavaScript doesn't fail for any reason) it will then take over for future interactions.
Otherwise, the regular links and forms you (should) have in the page will function as normal without JS.
I've been trying to get various routes bookmarkable within my app, and this is possible if I don't have pushState enabled. A user can enter mysite.com/#/view/30 and the proper view renders.
However, if I were to enable pushState and go to mysite.com/view/30 I receive a parse error (navigating there via the root page works fine).
I'm currently utilizing the Backbone.js Boilerplate using Require.js, and the parse error is appearing in my config.js file. I'm fairly certain the issue isn't with Require but I'm not completely sure. Frankly, I don't necessarily know what code to paste here either because I believe I'm more lacking a fundamental understanding a difference between hashbangs vs. pushState.
I've read up on the HTML5 feature, however the answer to my specific question still eludes me.
The page with your Backbone router on does not exist at the path you are pointing to in your pushState. The pushState is purely to change the URL representation. You'd have to do some server config changes to route all of your requests back to a main index file.