Workshop: How to create your own translation file for YOURLS

Version 1.6 YOURLS is fully “localizable”, ie translatable, and the translation process itself is very simple. We’re going to create a translation file, but first, a very little theory.

A… “locale” ?

The default language of YOURLS is U.S. English (or, to be accurate and fair, it’s “Ozh English”: it’s not my mother tongue so a few sentences may be sometimes a bit le suck ; if so please correct me :)

In nerd speak, that language is called a “locale”: a combination of language (English) and regional dialect (US, you know, colors and colours). Hence, the default locale of YOURLS is en_US.

YOURLS uses translation files that contain the strings in English and in their translated form. There are 2 files: a PO file, which is human readable, and a MO file, which needs to be generated by a script or software.

In this example, I’ll show you how to generate a translation for France’s French (ie fr_FR) using Poedit, a simple PO file editor, but everything will be very similar using another desktop tool or web based tool such as

Generate your translation file

  1. Install Poedit. Small download, simple install, no configuration, cross platform, free.
  2. Download the YOURLS.pot template file, rename it to fr_FR.po
  3. Open your fr_FR.po with Poedit
  4. Optional : fill in some translation details. To do so: click Catalogue / Properties. Leave other fields untouched, you don’t need them.
  5. Start translating. It’s really just about entering translated text in the Translation field. Be sure to copy any HTML tag, punctuation or seemingly cryptic bits such as %s that will be replaced within YOURLS by non translatable text (a URL for instance).
  6. Once you’re done, save your work: Poedit will save your modified fr_FR.po file, which is the human readable translation file, and will generate a file, a machine readable file and what YOURLS need to translate strings.

YOURLS 1.6 contains about 270 translatable strings. Some are very short (one or a couple of words), some a longer sentences, but overall the process isn’t too long or cumbersome. As an example, creating the complete French translation, fine tuning it (and fixing a couple YOURLS bugs by the way) then creating a repository to host the files took me roughly 75 minutes.

Check and fine tune your translation file

Test your file to check translations perfectly fit the context they are used in:

  1. in your config.php, add or edit the following:
    define( 'YOURLS_LANG', 'fr_FR' );
  2. drop the two PO and MO files in user/languages
  3. Play with YOURLS and check all pages and possible uses (shorten link, edit and delete stuff, etc…)

Distribute your files

Last step: make sure others can benefit from you hard work!

  1. Upload your two PO and MO files somewhere on the interweb. I recommend using a source controlled service, such as Google Code or Github: this will make your changes easy to track, your files easy to maintain, and others’ contributions easy to implement. If you don’t want to use SVN or Git, a regular hosting (your blog) will be fine
  2. Ping me! Open a new issue on YOURLS.pot and tell us where your translation lives. It must be a directory, or a page listing available translations, not a specific single file.

A list of available translations will be maintained.

Protips: what makes a good translation ?

Be fluent.
To be a good translator, you need to be very comfortable with English and the language you’ll translate to. Casual knowledge of one or both will result in a translation that will most likely sound awkward or unnatural to native speakers. In other words: this.

Don’t translate literally.
Maybe the English sentence will have a 2 part structure that won’t sound natural in your language, maybe a longer sentence or 3 smaller sentences will sound better. Adapt, refine, make it sound natural.

Keep the same tone
Some messages are very formal (eg “URL invalid” as an operation result) and some are less formal. Keep the same level of formality or informality, as it depends on the context in which string will be used.

Don’t over translate.
Some English words have become common enough that it may sound weird to translate them. For instance, it’s up to you to determine if “plugin” or “bookmarklet” have to be translated or if those words are better as is.

Bonus: Protips using Poedit

Hitting Control + Enter or Control + Down arrow will navigate to the next untranslated string. Hitting Control B will copy the source (untranslated) text to the Translation box, which can be handy if you have a few HTML tags to re-use.

Sometimes the Translation field will show a split field: it means you need to enter the singular and plural form of a sentence.

Sometimes you will also get a few hints in the Notes for translators area: these comments will help you understand the context of a string and help you pick the best translation.

Short URL to this post:

YOURLS 1.6 : translators wanted !

Change of plans for YOURLS 1.6. According to the RoadMap and previous posts here, the upcoming version 1.6 of YOURLS would introduce a new DB schema. But plans are made to be changed!


Localization has always been a long wanted feature for YOURLS (issue #58, opened more than 3 years ago in September 2009). It has always been planned, but low priority. Then, two things happened.

First, a couple month ago, I had to set up a YOURLS instance on a French corporate intranet. It immediately occured to me that the lack of translation API was going to make things a little more complicated than expected, given all the strings that were hardcoded in English. I always picture individual users such as myself not having a problem using simple software in English, but it’s a little different when you have to deal with a larger non-techie population.

Second, recently, @LeoColomb, a long time YOURLS user and prolific hacker, threw a patch in my face with the first draft of the translation API. Yep, in my face!

So, I decided to prioritize that feature. Over the last few days the committing pace has been unusually hectic and as of now, labelled 1.6-polyglot, YOURLS is ready to be fully translated.

Translators Wanted!

What does “ready for translation” mean exactly?

Instead of having hardcoded strings, such as echo "Woah awesome" and return "You are nice", YOURLS now uses the very common gettext functions, and you’ll see code like yourls_e( 'URL added' ) and return yourls__( 'You are nice' );. These functions search for the translated string in a translation file, if available, or otherwise return the original string.

More detailed documentation to help translators will be written later, but it’s a really straightforward simple process:

  1. Download YOURLS.pot, the translation file template
  2. Rename it to [your-locale].po, where [your-locale] is typically language code, underscore, country code (for instance in Portugal that would be pt_PT, while in Brazil it’d be pt_BR).
  3. Install a translation software: it’s nothing more than a text editor capable of reading .po files, showing you the untranslated string and a text box where you type in the translation, and saving a .mo file which is what PHP needs. A cross platform, simple yet complete editor is Poedit. There are also simple web based tools, such as PoEditor where you upload the .pot, translate, and download a .mo
  4. Once you have your fully translated pt_BR.po and the generated, host them somewhere (preferably on a source control enabled environment such as Github or Google Code to make contributions easier) and ping me! I’ll maintain a list of available translations.

To test your translation file as you create it :

  1. Download a nightly build or update via SVN
  2. Drop your pt_BR.po and files in user/languages
  3. Add define( 'YOURLS_LANG', 'pt_BR' ) to your config.php
  4. That’s it! Play with YOURLS

Translators, it’s important you join the party early: you’ll help us make sure the translation API works as smooth as expected, and win the “First YOURLS Translation Ever” award :)

What’s the Roadmap, then ?

On top of localization, which not everyone gets excited about, YOURLS 1.6 will bring the usual load of bugfixes and little enhancements. Better URL sorting and searching in the admin interface, more filters and actions to allow for more flexible and powerful plugins, a smarter API, better security and sanitization functions, plus more awesome and more w00t.

As usual, no ETA, but we’re speaking probably a couple weeks here. It really depends on the translator feedback.

Then it will be time to work on YOURLS 2.0 with the much awaited and needed DB structure change, and more goodness you’ll be able to handle. From a semantic versionning point of view, it just made sense anyway to give such a change its own major release number rather than a simple dot release.

There are even more news to share, but that’ll be another post :)

Short URL to this post:

It’s Alpha but it’s stable. For now!

As of writing, YOURLS version number says “1.6-alpha“. Despite boasting an intimidating “alpha” tag, it’s currently completely stable: I didn’t introduce yet any major change, especially in the DB structure, so feel really free to update today using SVN or with a nightly build. For the record, I’m using that version on and my personal, amongst others.

This said, expect some breakages in the future: I’ll slightly refactor the way action works, I’ll change a bit API returns, probably a few other things, and of course, there’ll be DB upgrading which is always the scary operation of all :)

After the stable version is released, there will be thorough documentation to help plugin authors update their code. No worries, that’ll be quick and simple.

When I’ll start implementing potentially breaker features, I’ll change the version number to something more frightening such as “1.6-alpha-dont-use“, so be sure to check it before you update on a live setup.

So, if you’ve always had ideas or thoughts for something crazy but not necessarily backward compatible, now might be a good time to suggest them :)

Short URL to this post:

Working on YOURLS 1.6 : the next DB structure

What’s up, gents? I’ve begun working on the next iteration and here’s what I’m up to.

YOURLS 1.5 : DB suckage

As everybody knows, the current database design in YOURLS is dumb and very inefficient. Its biggest flaw is that the keyword (ie short url) is repeated in both the URL and the LOG tables, making it absurdly difficult to update a short url without losing all historical data.

Another design decision I regret was to store stuff in case they would be useful to anyone, such as user agents in the log table. Since there’s no core feature using that info and I probably won’t implement any, this should not be there. There’s a plugin API for this.

There are a couple of awesome features I want to work on for YOURLS 1.6, one of them being the ability to store arbitrary data associated to any short URL — think url meta data, the way WordPress does it.

YOURLS 1.6 : previous thoughts

I’ve been pondering about the next DB schema for a very long time now, trying to think about the most state-of-the-art structure I could come up with (given my overall blatant lack of skill for DB things) and addressing all possible future features and current issues. I’ve proposed stuff and a few people have been kind enough to comment. But all this had one weakness : it was complicated and scaring me. Seriously :)

YOURLS 1.6 : smarter yet simple (at least I hope so)

I decided to make up my mind once for good and here is how I see things in YOURLS 1.6:

The main URL table will be properly normalized with a URL id to stop repeating the keyword across tables. I could probably go further in normalization (storing the long URL and title somewhere else, as I first thought) but that’s where I think it becomes too much trouble and hassle for too few benefits.

The URL_META table will store anything you’d like about a particular short URL and will be used by plugins: some tags, a note, a mime type to handle redirection differently, anything.

The LOG table will be trimmed down a bit, which — disk wise — should be beneficial to sites with lots of hits, and properly. Again here I could probably go further and normalize the referrer information, but what bothers me then is the number of DB queries needed for each short URL redirection, which I want to keep at a very minimum.

The LOG_META table, just as its meta sibling, will store anything you’ll want to store about a hit: the user agent, some cookie info, anything.

No big change in the OPTIONS table, just an autoload parameter so plugins will be able to store anything without loading that every time in RAM.

So, that’s it. If you have any thought or any “zomg dude don’t, terrible decision” warning to share, please do. We’ll see later for other DB novelties such as log archives or further optimization. I’d rather stop pondering and start coding :)

Short URL to this post:

YOURLS 1.5.1 Released

I’m happy to announce that YOURLS 1.5.1 is available and waiting for you. Get it quick, the first 1,000 installs get 20% off the regular price!

What’s new

YOURLS 1.5.1 is a “minor” release, as in “there are no really new important features but lots of improvements and bug fixes”. Some very cool stuff nonetheless, which are:

  • You can now encrypt your passwords in the config file instead of storing them in clear text. See Using encrypted salted passwords
  • YOURLS stat pages now uses the new Google Visualization API. See that page for example.
  • Stat pages are much more intelligently generated, SQL wise. That alone makes it worth upgrading
  • The API is now JSONP compliant, for all you Javascript nerds
  • Drop a favicon in the /user directory and YOURLS’ll use it

You can check a slightly more detailed changelog.txt and, if you’re really wanting to keep an eye on development, follow @YOURLS (for more general news about YOURLS, and other stuff, you’ll want to follow Ozh instead — much more entertaining :)

15 second updating

That’ll be a quick update: just upload the new archive to overwrite all your files, and that’s it. No scary update page to remind you that everything should go fine but you should backup everything just in case. Note that I’m not saying that you shouldn’t backup regularly anyway :)

Oh, and while you’re downloading the latest archive, spend a second or two on and give that “social” icons the spanking they deserve! The Showcase section has been recently updated and, man, there are quite a few cool things around made with or for YOURLS!

What’s next

I shall now start to make up my mind about the next database schema for 1.6 and work on the next iteration. This will imply lots of DB changes and I’m truly scared because this is my sucky area :)

I’m also currently pondering over moving the project on Github or not, see previous blog post on that subject.

OK, those last two paragraphs make me sound like I just can’t make any quick decision, but, Ma, I swear this isn’t what it looks like! :)

Now be a good boy and tell a friend to update while you’re updating, will you?

Short URL to this post:

Should YOURLS be on GitHub instead?

I’m regularly asked if there’s a chance that YOURLS be hosted on GitHub instead of Google Code as it is now.

Sure, GitHub is sexier, the web interface is much slicker, trendy and all. On the other hand, Google Code is here to stay forever or so, I know SVN, the YOURLS project has all its ticket and source history there and, despite being a bit raw sometimes, the interface and the service get the job done.

One argument I’ve been given a couple of times is “you’d get more contribution on GitHub”, but I’m not convinced: why would it be easier on GitHub (just because you just click “Pull Request” and save the minor step of generating a diff file?). The counter argument that easily comes to my mind is: spending hours on learning new tools and migrating the project and its history (issues and commits).

But maybe I’m not seeing the big picture and there are factual reasons why hosting on GitHub would be more beneficial to the YOURLS project. If you believe that’s the case, please do comment and convince me :)

Short URL to this post:

Forums are gone

I decided to remove the forums on this site. Long story made short: I’m uberfedup with dealing with spam and I’d rather do something productive with my too rare free time (and, to be honest, I’m surprised it lasted so long before I decided this)

So long, chinese spammers. Sorry for the (very few) users who felt this was useful.

Short URL to this post:

How to use Twitterfeed with your custom YOURLS URL shortener

For many, Twitterfeed means you have to use bitly. See, it is very easy to set up Twitterfeed to use your own YOURLS install and effortlessly publish tweets from a custom RSS feed using your own URL shortener. For instance, I do this on the @yourls account, where every source commit on the project gets tweeted.

Twitterfeed + custom URL shortener

To do so, create a new feed on Twitterfeed, and in the Advanced Settings, check “Post Link” and pick “Custom” as “Shorten link through” option. You’ll be given an input field to define your “Custom endpoint”. In this field, enter the URL of your YOURLS API, like so:


The important bits in this URL endpoint are:

  • the URL of your YOURLS API, obviously
  • your own secret signature
  • url=%@, because Twitterfeed will replace “%@” with the URL to shorten

Twitterfeed Advanced Settings

Have fun!

Short URL to this post:

YOURLS goodies: forums, nightly builds and hook list.

There are a few things I’ve discreetly mentioned over the past weeks, either on Twitter (follow me!) or through the project wiki pages, that are well worth an official blog post: forums, nightly builds and hook list.

1. Forums!

Some time ago, I’ve setup a few YOURLS forums. There are currently 3 forums:

  1. General discussion: show off your cool public interface or personalized YOURLS index page with stats and stuff, discuss anything, bounce ideas.
  2. Plugins: anything related to plugins. Introduce yours and ask for feedback, suggest plugin ideas.
  3. Help Wanted!: if you have a problem and need someone to lend a hand, try here. The project issue tracker is not suitable for personal support requests (its goals are to report defects or suggest feature requests, not troubleshoot your own unique personal .htaccess issue), but this forum is. Maybe some freelancers will even get a couple paid gigs here too?

If these forums do meet a need and become active, I may ask a few volunteers to help moderate it in the future.

2. Nightly builds!

There are now YOURLS nightly builds generated, well, every night. This is aimed at users who want to update their install (either to code plugins or to fix bugs without waiting for an official package) and don’t know how to update YOURLS with SVN.

For the record, unless stated otherwise the current trunk version of YOURLS is safe to run on a live site. For instance, I run it on and also my personal URL shortener,, and things have always been fine.

Remember: when coding plugins, it’s recommended to use the latest available, that is either running trunk or installing a nightly build. Which leads to me third point:

3. Hook list!

YOURLS plugin coders will be pleased to know that there is now an exhaustive and always up to date list of YOURLS actions and filters. This list is generated every night against the current trunk version, thanks to the help of a smart user who crafted a neat perl script.

Short URL to this post:

Hot: APC Cache plugin for YOURLS

I’m particularly excited by this one: Ian Barber got his hand dirty and wrote the first release of an APC Cache plugin for YOURLS.

In case that’s Greek to you, APC stands for Alternative PHP Cache and is a PHP extension that provides an opcode cache for PHP: it caches data and compiled code in memory. From the readme:

This plugin is designed to remove a lot of the database traffic from YOURLS, primarily the write load from doing the logging and click tracking. We have attempted to strike a balance between keeping most information, but spilling it in some cases in the name of higher performance.

If you have a server capable of running APC, especially if you’re running a popular URL shortener, please give the plugin a try and send Ian some feedback!

Short URL to this post: