Translations of folder names - two proposals



There seems to only be two basic ways of doing filename translations
of well-known directories (such as the desktop directory), one is using
well known static locations (like ~/Desktop) and translate the filename
in the ui, the other way is to have the translated filename on disk and
some sort of mapping that stores the location of the special directory. 

In this mail I will propose two implementations, one for each method,
then I'll discuss the pros and cons of them. 

1. The gettext method
=====================

Filenames are kept in English on disk, in well known location (like
~/Desktop). When you store references to the directory you store the
full non-translated pathname, and when e.g. copying files to it you
always know the target directory path.

However, whenever a filename is displayed you need to calculate the
display name for it. So, you need to call the following API:

const char *
some_lib_get_display_name (const char *pathname)
{
  const char *translated;
	
  if (g_str_has_prefix (pathname, g_get_home_dir ()))
    pathname += strlen (g_get_home_dir ());

  translated = dgettext ("filesystem", pathname);
  if (translated != pathname)
    return translated;
    
  return g_basename (pathname);
}

This allows us to translate files in the users homedir, and other
files in the unix tree if we want.

The main users of this API would be Nautilus, the file selector and the
file selector button widget. Its pretty uncommon for folder names to
appear in other places in the ui.

Users of the well known folders don't need to use any APIs, except
they need to know the hardcoded paths for the well known folders
they're using.

2. The symlink method
=====================

Filenames are stored on-disk in the translated form. To display them
you don't need to do anything in particular (unless you want to
display emblems or something for them). However, in order to know the
location of a well known folder you need to call some API that returns
the pathname of the directory.

To store the location of the folders we create symbolic links in a
hidden directory in the users home directory. So, for instance
~/.folders/desktop will be a (relative) symlink to "../Desktop" on an
english system, and to "../Skrivbord" on a swedish system. If there is
no such symlink the first time its requested we create a directory
with a name based on the current locale, and create the symlink to
it.

Its easy for quick-hack scripts to e.g. copy a file to the desktop
directory using this, but you have to be carefull when accessing the
folders so that you actually use the real folder instead of the
symlink. You don't ever want to go up from your desktop folder and end
up in ~/.folders. Also, you should avoid storing the expanded symlink
location in persistant storage, because the symlink may change later.

Furthermore, all apps that use the well known directories to store
something must use a specific API to get the directory, because if the
directory isn't yet created you have to know what directory name to
use for it, and only the system library knows that. 

So, the API would look something like (warning, pseudo-c):

typedef enum {
 GNOME_FOLDER_DESKTOP,
 GNOME_FOLDER_TEMPLATES,
 GNOME_FOLDER_PUBLIC,
 ...
} GnomeFolderType;

char *
gnome_folder_get_location (GnomeFolderType type,
                           gboolean create_if_not_existing)
{
  char *symlink;
  char *location;
  
  symlink = g_build_filename (g_get_home_dir (),
                              ".folders/",
			      symlink_name[type],
			      NULL);
  if (g_file_exists (symlink)) {
    /* creates absolute filename, without ".." etc */
    return resolve_symlink (symlink); 
  }

  location = NULL;
  if (create_if_not_existing) {
    location = g_build_filename (g_get_home_dir (),
                                 gettext (symlink_name[type]),
				 NULL);
    mkdir (location, 0600);				 
    symlink (symlink, "../" +  gettext (symlink_name[type]));
  }

  return location;
}		


Advantages of the methods:
==========================

Its not obviously clear that any solution is superior to the
other. Each method has its advantages:

Advantages with the gettext method:
* Extremely easy for all sorts of programs to use the well known
  directories, without needing to link to any gnome libraries
* Filenames as displayed in the UI always display in the current
  locale. Even if the translation is later updated or added, or if you
  change to another locale.

Disadvantages with the getttext method
* All UI applications need to be modified to use the translated
  display names. This means we need to create a freedesktop.org
  standard and get the other desktops to buy into this idea and
  implement it. If we don't, the users home directory will look
  different in apps using different toolkits.
* Slight performance degradation due to having to call gettext() for
  all filenames. I did some measurements here: 100000 failed gettext
  calls was about 400 msecs on my box, so its not a large problem, but
  there is a cost. 

Advantages with the symlink method:
* No modification needed to applications that don't use well known
  folders. We might still want to create a freedesktop standard, but
  an application not using the spec won't cause problems unless its
  also creating well known directories using a different method.
* The user can actually manually change the name or location of the
  well known folders if he want. He just has to change/create the
  symlinks.

Disadvantages with the symlink method:
* There is a risk that apps don't follow the protocol when locating
  the well known directories. This means an app that e.g. downloads
  to the desktop might create a ~/Desktop directory, even if I already
  have a ~/Skrivbord one.
* Once the directory is created with a translated name it will always
  keep that name, even if you switch to a different locale, or if the
  translation in the locale changes.
  This is going to be pretty common. People log in initially in the
  default language (typically english) before they manage to figure
  out how to change their locale to what they want. In fact, unless
  they already know you can use gdm to pick language before they even 
  login they are basically forced to log in in english to figure out how 
  to change locale. For KDE this is even worse, since you *have* to log
  in to change the locale (I think).
  
Some things are not clearly better with any one of the solutions. For
instance with the gettext method the names will be in english in the
terminal. This might be bad because it differs from what the UI shows,
and it might be good, because it fits in with the terminal using
english for everything else (command names, env vars, arguments, etc),
and its easier to display on things like terminals and over remote
logins.
  
Another important question is when and where we create the
director�. One option is to have them in the default user homedir
(/etc/skel or whatever) which will only be possible with the gettext
method, another is to create all of them on login (plus create some
file signifying that the folders have been created already so we only
do this the first time), and finally we could let applications create
them as needed. Letting apps create them means they'll just suddently
show up while using some app, which might be a bit suprising. It also
makes it harder if the user want to get rid of the folders, since
they'd just be recreated when needed again.

I'm not sure what the best solution is here. Technology-wise I prefer
the gettext approach, but the thought of going through the whole
freedesktop.org standardization process again scares me a bit.

What are peoples thoughs on this?





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]