NOC Diary Week 8: Translation and Draggable

This week was the eighth week of my internship at 9cv9 as part of the NUS Overseas College (NOC) Southeast Asia programme. This week, I worked on two interesting tasks and would like to write about how I was able to accomplish them.

The first interesting task at hand was translation. The website UrbanCV was new and only supported English at the moment, but needed to support other languages, such as Indonesian and Vietnamese (the main target markets) as well. Luckily there is a handy library called next-translate to help us. (Just an interesting note, 9cv9 uses react-i18next to handle translations, which is what next-translate is actually based off, just optimised for NextJS). The usage of this library is actually pretty simple. First you need a i18n.js config file, where you specify the languages in locales, the default language and which pages use which translation files.

{

  “locales”: [“en”, “vi”, “id”],

  “defaultLocale”: “en”,

  “pages”: {

    “*”: [“common”],

    “/”: [“home”],

    “/about”: [“about”],

    “/onboarding”: [“onboarding”],

    “/choose-template”: [“chooseTemplate”]

  }

}

Secondly, you have to create the files containing the translations, according to the name spaces specified earlier, in the /locales directory.

├── en

│   ├── common.json

│   └── home.json

├── id

│   ├── common.json

│   └── home.json

└── vi

    ├── common.json

    └── home.json

Each json file will contain keys mapped to sentences that you wish to translate. An example in the English file is:

{

  “title”: “Hello world”,

  “variable-example”: “Using a variable {{count}}”
                          // supports variables

}

You can then easily use these translations with a functional React component using the useTranslation hook.

import React from ‘react’;

import useTranslation from ‘next-translate/useTranslation’;

export default function Home() {

  const { t } = useTranslation(‘home’);

  return (

    <>

      <h1>{t(‘title’)}</h1>

      <p>{t(‘variable-example’, {count: 3})}</p>

    <>

  )

};

The second task I did was to implement a draggable component. After much research, the library I liked the most was react-beautiful-dnd. One really interesting thing is that the creators of this library actually made a 1h free course on egghead to teach users to easily use their library.

The usage of the library involves using 3 components, DragDropContext, which wraps the part of your application you want to have drag and drop enabled for, Droppable, the area that can be dropped into and finally Draggable, which is the element that can be dragged around.

I will briefly summarise the basic usage of each component with examples(from my notes taken from the video and official documentation), but if you wish for more detailed notes, check out this useful repository with community notes created or the actual repository of react-beautiful-dnd.

1. DragDropContext

  • Wrap whole component with DragDropContext, with onDragEnd function as a prop

2. Droppable

  • Needs droppableId prop (a unique id to identify the column. If you only have one droppable column, it’s not really important and you can name it whatever you want.)
  • Uses render props pattern (ie. needs to wrap a function returning the draggable components)
  • Note: the function receives an argument named provided and the outermost returned component needs to have a ref prop and contain placeholder as a child (to fill up space when an item is dragged away).

<DragDropContext onDragEnd={onDragEnd}>

  <Droppable droppableId={id}>

    {provided => (

       <Box ref={provided.innerRef} {…provided.droppableProps}>

         … /** insert Draggable items here **/

         {provided.placeholder}

       </Box>

     )}

  </Droppable>

</DragDropContext>

3. Draggable

  • Needs droppableId prop (a unique id to identify the draggable element)
  • Needs index prop (to know which position it is at)
  • Uses render props pattern as well (make sure to pass in the highlighted props below)

<Draggable draggableId={this.props.task.id} index={this.props.index}>

        {provided => (

          <Box 

            {…provided.draggableProps}

            {…provided.dragHandleProps}

            innerRef={provided.innerRef}

          >

            … /** insert content in Draggable element **/

          </Box>

        )}

      </Draggable>

Lastly we need to handle updating the state when the element is dragged. This can be done in the ondragEnd function, which receives the following object in as an argument:

{

  draggableId: ‘draggable-id’, // string

  type: ‘TYPE’, // string

  reason: ‘DROP’, // ‘DROP’ | ‘CANCEL’
  source: { 

    droppableId: ‘column-id’  // string

    Index: 0 // number

  },

  destination: {  // null if dropped outside droppable

    droppableId: ‘column-id’  // string

    Index: 0 // number

  }

}

An example of onDragEnd using this result is as follows:

const onDragEnd = (result) => {

  const { destination, source, draggableId } = result;

  // if destination is not null and position of item is not the same

  if (destination && !(destination.droppableId === source.droppableId    

        && destination.index === source.index)) {

    const newOrder = […tasks];

    const shiftedTask = task.find((e) => `${e.id}` === draggableId);

    if (shiftedTask) {

      newOrder.splice(source.index, 1);

      newOrder.splice(destination.index, 0, shiftedTask);

      setTasks(newOrder); //update state here with new array

    }

};

Marcus Tang
Marcus Tang
Marcus is a 2nd year computing student at the National University of Singapore. He has great passion in Computing and both Frontend and Backend engineering.

Latest posts

10 Best UI/UX Design Courses in 2021 (+Tips)

User interface (UI) and User Experience (UX) design are two of the most demanding skills that have dominated so far in 2021. Getting advancement...

Django Periodic Task with Celery Task Queue

Task Queue? Periodic Tasks? What are they? Task Queue is a way of organizing work or tasks in programs asynchronously, without a user’s request, and distribute...

Understanding Models, Views and Serializers in Django

Soo we are back once again this week, talking about models, views and serializers — essentially everything you will need to get an up-and-running...

More from author

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related posts