Leveraging xgettext for extracting translatable content from VueJS files

Attempting to utilize xgettext for extracting translatable strings from a VueJS file has presented some challenges. Specifically, xgettext does not seem to recognize JavaScript code within a computed property in VueJS.

For instance, consider the following element in the <template>:

<input :placeholder="translator.gettext('Phone')" />

Unfortunately, this snippet goes unnoticed when executing xgettext with parameters such as:

xgettext --from-code=UTF-8 --language=JavaScript

On the other hand, if a translatable string is used within a function call, it is successfully identified. For example:

<div>{{ translator.gettext('This is picked up 1') }}</div>
<input :placeholder="translator.gettext('This is NOT picked up')" />
<div>{{ translator.gettext('This is picked up 2') }}</div>

In this case, the translatable string inside the input placeholder remains undetected, while the other two are recognized.

The issue seems to stem from xgettext treating content within an HTML property as a plain string, while VueJS interprets any value prefixed by a : as valid JavaScript execution.

Is there a solution or workaround that would enable xgettext to acknowledge this JavaScript code instead of simply treating it as a plain string?

Answer №1

In my opinion, translating attributes may not be supported. One workaround could be to utilize a computed property for this purpose:

computed: {
   translatedPlaceholder () {
     return this.translator.gettext('This is a text')
   },
},

You can then integrate this computed property into your template like so:

<input :placeholder="translatedPlaceholder" />

Alternatively, you could create a custom filter for translation:

Vue.filter('translate', value => {
  return !value ? '' : Vue.prototype.translator.gettext(value.toString())
})

And then use it in your template as follows:

<input :placeholder="'This is a text' | translate" />

Answer №2

To tackle this issue, we took a unique approach by duplicating the /resources directory (which contains translations exclusively) to /resources-for-pot. We then proceeded to handle this temporary folder in the following manner:

1.) We copied *.js files (as the backend code also has translations) but removed lines that do not contain gettext( (including pgettext and npgettext), replacing them with empty lines to maintain an equal number of lines in the new JS file.

2.) Similarly, we copied *.vue files but omitted lines without gettext( content (including pgettext and npgettext), replacing them with empty lines to retain the original line count. Subsequently, non-empty lines containing translations were individually processed using jsdom https://www.npmjs.com/package/jsdom. We extracted all nodes using

nodes = (new JsDom(lineOld)).window.document.body.childNodes
, collected attribute values from each node, along with node.textContent, and combined everything using spaces. This resulted in a new line encompassing all translations from attributes, text nodes, and more.

3.) We scanned the /resources-for-pot directory using a customized parser in Poedit or directly through xgettext (utilizing Python as the language).

4.) Finally, we deleted the /resources-for-pot directory for clean-up purposes.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to conceal an HTML element on a particular page that is already styled as (visibility: visible), but only if its child has a specific class assigned to it?

I have a grid of content and posts displayed on multiple webpages. Users can select specific items from the grid to navigate to more detailed information on another page. Each webpage has its own grid which I want to filter based on a specific class. The ...

How to Test React Js API Calls with Jest?

I'm currently in the process of writing test cases for my API call function, but I'm encountering difficulties as I am unable to successfully run my tests. Below is the code for the API call function and the corresponding test cases. export async ...

Automatically populate a dropdown menu with options based on the user's birth date

I successfully managed to populate the drop-down fields for months, days, and years. Furthermore, I was able to calculate the age of the user; however, I have restricted it to a maximum of 13 years. Check out the code snippet below: $('#reg-yr' ...

Creating a function to manipulate an element on a different webpage

Upon clicking a button on Page1, a function is triggered which then calls another function to generate HTML and append it to a div with the #lista id. The issue here is that #lista belongs to Page2, so I am unsure if there is a syntax similar to ajax where ...

Steps for refreshing a React component following a data fetch operation

Currently, I am in the process of learning how to use React for building web applications. I have a basic React app that demonstrates the following features: Fetching a list of users Displaying the names of the users on individual cards once they are fetc ...

Having trouble with my jQuery .hover() code not running as expected

Whenever I hover over my divs, I want them to change color. However, the code doesn't seem to be working as expected when I try to do so. I suspect that the issue might be related to the z-index property used in the class that I am trying to hover ove ...

Is there a way to incorporate onComplete and onAbort callbacks with <router-link> similar to router.push(location, onComplete?, onAbort?)?

It is common knowledge that the onComplete and onAbort optional callbacks can be used as the 2nd and 3rd arguments in the router.push method. router.push(location, onComplete?, onAbort?) These callbacks are triggered when the navigation is either success ...

Using VueJS and Jest: A guide to testing and spying on methods triggered by watchers

Here is a snippet of code showcasing VueJs components. It includes a watcher and a method implementation. computed: { ...mapGetters({ resourceLinks: `tools/${storeGetters.resourceLinks}`, }), }, m ...

Pattern for validating mobile numbers with extensions using regular expressions

I am struggling to combine multiple separate regex validations into one for my mobile number validation requirements. The criteria include validating mobile numbers with a country code or starting with 00, as well as checking if they contain an extension n ...

Can Python's datetime object be used interchangeably with a JavaScript date object?

Take for instance in python, a date might look like: 2020-06-19T11:32:16.548109Z, is there a method I can utilize to transform this into a javascript Date object? ...

generate a cookie within a pop-up window

Can someone help me figure out why my Modal Window with a cookie to display only once isn't working? I followed this tutorial at . Here is the link to my website: Here is my code: <div class="modal fade" id="myModal" tabindex="-1" role="dialog" a ...

Leveraging the outcome of a Promise within webpack's configuration file

Currently, I am facing a challenge in accessing a Promise which is essentially an array of file paths created within recursive.js. This script navigates through my directories and organizes my stylesheets. The main issue arises when trying to utilize this ...

Sending numerous array values from datatables

I am currently working with datatables that allow for multiple selections. When I select 3 rows from top to bottom (as shown in this picture), the console.log returns this specific value for each row selected. The value that needs to be passed to the next ...

Counting the number of visible 'li' elements on a search list: A guide

In the following code snippet, I am attempting to create a simple search functionality. The goal is to count the visible 'li' elements in a list and display the total in a div called "totalClasses." Additionally, when the user searches for a spec ...

Challenging glitch in the JavaScript code

My jQuery code seems to be functioning properly in online text editors like Fiddle and StackOverflow snippets. However, when I try to implement the same code in Brackets or view it on GitHub, the navbar scroll down animation fails to work as expected. You ...

Transform C# ASPX to handlebars format

Initially, my task was to choose and relocate a single li from many options into a different div. But now, I am required to achieve the same result using a JS template which utilizes handlebars. The C# section is as follows: <li class="l-row__item pr ...

What is the best way to include temporary attributes on a mongoose object solely for the purpose of a response, without saving them to the database

I am looking to add extra temporary properties with additional data to the response but have encountered some difficulties. 'use strict'; var mongoose = require('mongoose'); var express = require('express'); var app = expres ...

Preventing ReactJS tooltips from exceeding the boundaries of the screen

Here is a simple demo showcasing blocks with tooltips that appear when hovered over. However, there seems to be an issue with the functionality. The tooltip should ideally be displayed either from the left or right side of the block. To determine the size ...

Steps to create a responsive array data in a Vue template

<template> <button v-on:click="modify"> modify </button> <div v-model="lists">{{ lists[0] }}</div> </template> <script> export default { methods: { modify: function() { console.log(this.lists) ...

Attaching events to the window in Vue.js

Having recently started working with Vue.js, I have come across a problem related to attaching and detaching keyboard events to the window within one of my components. Below are the methods I am using: created() { this.initHotkeys(); }, beforeDestroy() ...