Search code examples
reactjstypescriptspliti18nextreact-i18next

Is there a way to split a i18n translation?


OK, so I got this component that animating my titles. But know, I want to translate my application with i18n, but problem is, I was using .split() function to make an array of words of my titles, I know that .split() is taking only string, and all I tested return me a JSX Element. So I can't split my pages title.

Is there another way to do it, to keep my translation ?

Here is an exemple of my pages with the component title and what I tried (I also tried with Translation from react-i18next, but same result)

About.tsx

import { useEffect, useState } from "react";
import AnimatedLetters from "../AnimatedLetters/AnimatedLetters"
import { Div } from "../Layout/Layout.elements";
import { useTranslation, Trans } from "react-i18next";


const About = () => {

    const [letterClass, setLetterClass] = useState<string>('text-animate');
    const { t, i18n } = useTranslation();

    useEffect(() => {
        setTimeout(() => {
          setLetterClass('text-animate-hover')
        }, 3000)
    }, [])

    const getTranslation = (value: string) => {

        return <Trans t={t}>{value}</Trans>;
    }

  return (
    <Div>
        <div className="container about-page">
            <div className="text-zone">
                <h1>
                    <AnimatedLetters
                        strArray={getTranslation('About.Title').split("")}
                        idx={15}
                        letterClass={letterClass}
                    />
                </h1>
                

        </div>
    </Div>
  )
}

export default About

Before decide to translate, I was making like that :

<AnimatedLetters
    strArray={"About us".split("")}
    idx={15}
    letterClass={letterClass}
/>

AnimatedLetters.tsx

import { FunctionComponent } from "react"
import { Span } from "./AnimatedLetters.elements"

type Props = {
    letterClass: string,
    strArray: any[],
    idx: number
}

const AnimatedLetters: FunctionComponent<Props> = ({ letterClass, strArray, idx }) => {

  return (
    <Span>
        {
            strArray.map((char: string, i: number) => (
                <span key={char + i} className={`${letterClass} _${i + idx}`} >
                    {char}
                </span>
            ))
        }
    </Span>
  )
}

export default AnimatedLetters

Solution

  • OK I found it! I put the solution here in the case of someone else needs it!

    In fact there is two ways, don't forget that I needed an array to transmet to my component, so the first was to put directly an array into my translations json files, like:

    common.json

    {
        "Title": ["A","b","o","u","t","","u","s"]
    }
    

    But i did not thought that was very clean.

    So the second way was to create a method that tooks the key of the json file, to return it directly, like this :

    const getTranslate = (value: string) => {
            return (`${t(value)}`)
    }
    

    Then I stringify it to can use .split() to make an array

    const getTranslate = (value: string) => {
            return JSON.stringify(`${t(value)}`).split("")
        }
    

    The translate and the array worked nicely, but it returned with double quotes. The last thing was to erase it, with a replace and a little regex, and now : everything works like a charm 😁

    All the component looks like it now :

    About.tsx

    import { useEffect, useState } from "react";
    import AnimatedLetters from "../AnimatedLetters/AnimatedLetters"
    import { Div } from "../Layout/Layout.elements";
    import { useTranslation } from 'react-i18next';
    
    const About = () => {
    
        const [letterClass, setLetterClass] = useState('text-animate');
        const { t } = useTranslation();
    
        useEffect(() => {
            setTimeout(() => {
              setLetterClass('text-animate-hover')
            }, 3000)
        }, [])
    
        const getTranslate = (value: string) => {
            return JSON.stringify(`${t(value)}`).replace(/\"/g, "").split("")
        }
    
      return (
        <Div>
            <div className="container about-page">
    
                <div className="text-zone">
                    <h1>
                        <AnimatedLetters
                            strArray={getTranslate('Title')} // <<--- Called here
                            idx={15}
                            letterClass={letterClass}
                        />
                    </h1>
    
                </div>
    
    
            </div>
        </Div>
      )
    }
    
    export default About