Implementing localized 404 page with Firebase hosting

后端 未结 2 1533
一生所求
一生所求 2020-12-04 02:57

Say my web app has two locales: English(myapp.com/en/) and French(myapp.com/fr/). I want to localize my 404 pages, so that request to myapp.c

相关标签:
2条回答
  • 2020-12-04 03:28

    This answer is outdated. Firebase now supports this functionality by default. See the correct answer.


    One way of achieving this functionality is by using rewrites:

    {
      ...
      "hosting": {
        "rewrites": [
          {
            "source": "/fr/**",
            "destination": "/fr/404.html"
          },
          {
            "source": "**",
            "destination": "/en/404.html"
          }
        ]
      }
    

    This will serve the /fr/404.html/ page for unmatched requests inside /fr/ directory and /en/404.html for any other unmatched request.

    The downside of this approach is that the returned status code is 200 instead of 404.


    A better solution is to rewrite unmatched requests to Cloud Functions that return the needed 404 page and the 404 status code. Note, that the 404 pages have to be located in functions/lib directory, not public.

    Also, with the use of proper Cache-Control header, you can allow the Firebase Hosting to cache the output of the Functions so that they don't have to run every time a 404 page is requested.

    Firebase config:

    {
      ...
      "hosting": {
        "rewrites": [
          {
            "source": "/fr/**",
            "function": "pageNotFoundFr"
          },
          {
            "source": "**",
            "function": "pageNotFound"
          }
        ]
      }
    

    The functions:

    exports.pageNotFound = functions.https.onRequest((req, res) => {
        res.set("Cache-Control", "public, max-age=31536000")
        res.status(404).sendFile("en/404.html", {root: __dirname})
    })
    
    exports.pageNotFoundFr = functions.https.onRequest((req, res) => {
        res.set("Cache-Control", "public, max-age=31536000")
        res.status(404).sendFile("fr/404.html", {root: __dirname})
    })
    

    But this approach duplicates the code and can be messy in case you have more languages.


    It would be better to extract the request handler into a function:

    exports.pageNotFound = functions.https.onRequest(notFoundHanler("en"))
    exports.pageNotFoundFr = functions.https.onRequest(notFoundHanler("fr"))
    
    function notFoundHandler(lang) {
        return function (req, res) {
            res.set("Cache-Control", "public, max-age=31536000")
            res.status(404).sendFile(`${lang}/404.html`, {root: __dirname})
        }
    }
    

    Update: I filed a feature request for multiple 404 pages to Firebase and they replied that it will be taken into consideration.

    0 讨论(0)
  • 2020-12-04 03:32

    As of August 12th 2020, Firebase Hosting now includes support for i18n internalization.

    Here's how to use it:

    1. Create a new directory to host these localized files (e.g localized) under your public directory.
    2. Update your firebase.json file to include a reference to this new directory:
    // firebase.json
    
    "hosting": {
    
      "public": "public",
    
      "ignore": [
         // ...
      ],
    
      "i18n": {
        "root": "/localized"  // directory that contains your "i18n content"
      }
    
      // ...
    }
    
    1. Under the localized directory, create a new directory named fr, and that's where you can add your french 404.html file.
    2. Run firebase deploy to deploy your site and now your french users should be redirected to the correct page :)

    See the Firebase Docs for more information on country and language codes.

    0 讨论(0)
提交回复
热议问题