三太子(Nalakuvara)計畫:Building Opera Nalakuvara

Nalakuvara is one of the most famous customized Opera packages in Taiwan. It is cross-platformed, open-sourced, unobtrusive, multi-lingual and fully localized for Taiwan users. This article focuses on technical details of managing such an Opera customization project.

Introduction

Opera Desktop Browser ("Opera") is an elegant web browser. It follows web standards strictly, ships with so many functions built-in, and still runs so fast, even on older computers. Although Opera remains proprietary, it have an open mind: basically Opera encourages user communities to build their own customized Opera to suit their own needs, as long as people do not break Opera's End-User License Agreement. (i.e., people shall not modify, translate, reverse engineer, decompile or disassemble Opera Browser or any part thereof or otherwise attempt to derive source code, create or use derivative works therefrom. etc.)

As the result, there are many customized Opera around the world. Some customized Opera are semi-officially supported, while some are even becoming official. Opera Ibis ("Ibis"), once a community-based customized Opera from China, is now listed as an official download on Opera's official website. Ibis is basically identical to international version of Opera, but available only in Simplified Chinese and English interface, and with some default setting modified. (In v9.6x era, Ibis also ships with special skin, and has a slightly different rendering system for Simplified Chinese characters. The rendering system in Ibis 9.6x later merged into Opera 10.00 trunk.)

Ibis reveals some special needs from OperaChina community. Not too surprising, users from Taiwan have similar yet different needs, which will be discussed later, in "Background Analysis" section.

Thus there is Opera Nalakuvara ("Nalakuvara"), a customized Opera project for users from Taiwan. Nalakuvara is still young, but already attracts more than 5,000 downloads in the first half month since its Beta 1 release. Web media such as Chinese Engadget and Plurk spread Nalakuvara widely. Some local web service providers also promise to improve their products to be compatible with Nalakuvara.

Nalakuvara is quite special among all Opera customization projects. First of all, Nalakuvara is quite open. The whole Nalakuvara is well documented and reveals almost everything to users. One could easily adapt Nalakuvara and fork to his/her own project. Second, Nalakuvara is extremely flexible and cross-platformed. For now, there are 9 packages for various systems including Windows, Linux (Ubuntu, Fedora, and generic Linux), and FreeBSD; package for Mac OS X is on the way, too. Third, Nalakuvara is exceedingly user-friendly; users could choose if he/she would like to install any of 3rd party components in Nalakuvara. Nalakuvara confirms before deleting exist user profiles (or make backup instead, in some platforms). It also enables User JavaScript related options only if users choose to install any of them. If there is anything users need to do by themselves, Nalakuvara provides detailed information. Even if installed in Windows other than Traditional Chinese environment, Nalakuvara still displays and works mostly correctly.

In this article, I will describe how I manage Nalakuvara project, piece by piece, with lots of technical details. Take this article as a reference, one could easily start-up a brand new customized Opera project that works. The outline of this article is as follows:

OK, here we go!

Planning

Always plan first for any project. Think carefully before action. In this stage, a project manager has to figure out what to do, and what not to do. Without planning, a project might lose focus and finally be forgotten. Make sure your project will be noticed, remembered, and understood once made public, one way or another.

Background Analysis

First step in the plan stage is to see what has to be done in the first place. To achieve this, one has to understand the (possible) community behind the project. There are many different methodologies to do this job. In Nalakuvara, I took some relatively easy ways: first I did some hallway tests, then I study from local forums.

A hallway test is a common usability test: you randomly invite people who just walk through a hallway to use your product, and watch his/her action and response. So I ask several random people using Opera 10.00 to do their daily browsing. If they complain anything, no matter a feature just disabled by default or totally absent in Opera, I write it down. On the other hand, if they find any feature quite handy or lovely, I write it down too.

A hallway test allows to observe common average users. But I have to understand heavy users and newbies, too. Therefore, I visited a forum focusing on "Browser" in Ptt BBS, the largest local telnet-based BBS in Taiwan. There are over 100,000 unique users logged-in PTT at the same time every night. Heavy users and newbies exchange their knowledge in PTT, so one could see most frequently requested features among all browsers there.

With information from hallway tests and PTT, I figure out that most of users from Taiwan would like to:

  • Change Opera's UI font to MingLiU (the default Traditional Chinese font from Traditional Chinese version of Windows) rather than SimSun (the default Simplified Chinese font from Simplified Chinese version of Windows);
  • Use mouse gesture;
  • Use drag and drop;
  • Open new tab in background when possible;
  • Avoid using Chinese URL;
  • Search strings directly in the location (URL) bar;
  • Use Gmail / Ymail / Hotmail;
  • Search with Google Taiwan / Yahoo! Taiwan / other search engines popular in Taiwan;
  • Use dictionaries;
  • Block web advertisement;
  • Convert Simplified Chinese characters to Traditional Chinese within a web page;
  • Render web page with IE's engine (Trident) to use ActiveX or view IE-only web page in an Opera tab, without opening IE (so called "IE Tab");
  • Connect to BBS sites via telnet:// protocol within the browser;
  • Use popular Firefox Extensions or equivalence.

So the stage is set. Luckily, most of these requested functions are built in Opera, one just need to enable them; some others are doable via User JavaScript. It seems not so hard, at least so far.

Then I prepare for the first test run. I grab a portable Opera@USB 10.00 build, enable and tweak some settings, which would be discussed in "Dive Into Opera" section, and do a hallway test again!

The Love-to-Complain rate is significant higher then first hallway tests. With this result, I knew this project is worth to do, and there is still a long way to go.

Naming

So next step is to pack a beta package available for public. But wait, before any project is made public, it need a name.

Name, the magic word in human languages. It is name that makes invisible things visible, abstract ideas concrete, communication focused. With a name, people know what each other are talking about.

So you have to name your project.

Before I name mine, I start thinking of Ibis. Ibis, the Vermillion Bird of the South, one of the Four Symbols of the Chinese constellations, is an elegant and noble red bird both in appearance and behavior. Ibis is, thus, a great name for Chinese customized Opera project. It got the right color and meaning. "What will be a good name for Taiwanese customized Opera project?" I asked myself.

One night, I had small talk with one of my friends. He suggested that I choose from some Deity names in Taiwanese traditional religion. Soon, Nalakuvara jumped into my mind. Nalakuvara, or Nezha, is a Deity in sanskrit sutra. Taiwanese people adapted this Deity into our own religion system, just like we adapted numerous different culture and technologies into our own. In Taiwanese folk tale, Nalakuvara is a vigorous and dexterous Deity. He has many talismans, including Wind-Fire-Wheel, with he runs faster than others. The theme color of Nalakuvara is also red. So this project is named Nalakuvara.

When naming your project, please remember that it is impossible to satisfy all users. No matter how brilliant your project is named, there is always someone who does not like it. A name is a name. Do not spend too much time on naming. Keep yourself concentrating on the actual project, and let your project do the talking job.

So there was Opera Nalakuvara Beta 1, the very first public release of Nalakuvara project. From that time, Nalakuvara has faced living and changing user environment. There must be something I missed. I had to improve its overall usability, fix its bugs, add features people still desire. Tons of work to do, how could I keep it straight?

Guidelines

For every scaled project, there are road-map, milestone, and etc. These documents are the rules of a project. Nalakuvara is not one of these projects. Remember, it is still tiny from beginning. However, to keep Nalakuvara moving toward the same direction, there must be some guidelines. In Nalakuvara, these guidelines are:

  • Do no harm first, do something useful second;
  • Keep Opera look and feel just like Opera;
  • Cross-platform as possible;
  • Use as less 3rd party components as possible;
  • In case a 3rd party component is unavoidable, at least let users to make the final decision.

It is critical to write down these guidelines first. Anytime a dispute is raised, it is easy and clear to judge with these guidelines. When you work on a project on your own, you will find it your savior when facing user community; when you have a group of core members, these guidelines keep everyone on his track, minify possible misunderstanding among you.

By Nalakuvara's guidelines, I could respond to communities that might and might not be part of Nalakuvara:

  • Nalakuvara may not modify the official Opera installation package;
  • Nalakuvara may not cause security flaw;
  • Nalakuvara may not use Add-On applications such as eDown and oGet;
  • Nalakuvara might alter default menus and toolbars to provide additional feature;
  • Nalakuvara might use User JavaScript to provide additional feature;
  • Nalakuvara may not use User JavaScript that alters web page rendering result too much (so that it will not look and feel like Opera anymore);
  • Nalakuvara should enable User JavaScript options only if there is any User JavaScript installed;
  • Nalakuvara should allow users to select install location when possible;
  • Nalakuvara should allow users to choose what 3rd party components to install;
  • Nalakuvara should allow users to override default setting.

So far Nalakuvara almost meets all these goals, with the "IE Tab" feature the only exception: it works only on Windows platform, and a 3rd party Plug-In is required.

Tools

A good project needs good planning, and a handy set of tools. Good planning keeps your project on track, while handy set of tools get real things done. Here are some "must haves" while developing software project such as Nalakuvara:

Version Control

Version control not only is for team work but also for individual development. When using with team, version control mainly solves conflict from different team members; when out of team, version control helps you manage your project "versions." You could fork your project, merge fork back to trunk, tag versions, diff two versions, and most importantly, revert files to working versions.

Eventually, people make mistakes. Minor mistake costs you minutes to fix, a huge one destroys the whole project. You might accidentally delete a directory, convert important file to wrong format, or forget what you have done last night. Even worse, your system might fail, hardware might damage, or be stolen.

Version control could almost save you from such a disaster. Plus, it helps further collaboration with others (or tomorrow version of yourself). There is no reason not to use version control.

There are many popular version control systems, such as Subversion/svk, Perforce, git, and so on. In Nalakuvara, I choose Perforce. The reasons are:

  • I already use Perforce for years;
  • Perforce provides free licensing for Open Source development, and two-users with five-client-workspaces without a license for non-commercial usage;
  • Perforce is suitable for wide range situation, from single simple project to huge company like Google (that is right, Google uses customized Perforce);
  • Perforce is cross-platformed, with native binaries on several operating systems;
  • Perforce works great with both command-line and GUI;
  • Perforce does not leave .svn directory everywhere (which Subversion does).

Of course, you do not have to use Perforce. But any version control system is at least 1,000 times better than none! In my case, all my working, including text writing, commit to my Perforce server.

When working with version control systems, you should always check out files before editing, check in files after daily work, bug fixed, or things going right, and write logs when committing. There are hundreds of commit I made in the first two weeks of developing Nalakuvara. Without commit logs, it is impossible to target the right version to work with.

Scripting

In Nalakuvara, I do not alter the original installer of Opera. All changes I made are applied via script. There are several concerns on choosing script languages:

  • Should be native supported by operating systems, or could be compiled to native binary so that users will not have to install additional runtime environment;
  • Should be consistent with original Opera installers on different operating systems so that users will have better experience during installation or patch;
  • Should have GUI or command-line interface base on different conveniences on different operating systems;
  • Should be able to do specific works, such as reading/writing .ini files or Windows registry.

Opera supports many different operating systems. On Windows, original Opera installer is GUI-based, and allows users to choose install path and options; on Linux, Opera packages work with different package management systems like RPM, or are distributed as a tarball, with minimal or none install option; on FreeBSD, most users install Opera via ports; Mac OS X is totally another story. Sorry I will not talk much about Mac in this article for I never have a Mac.

I choose AutoHotKey for Windows jobs. Because:

  • AutoHotKey is a free and open-sourced;
  • Syntax is simple and easy, including GUI creation;
  • Could do Windows-specific works;
  • Could be compiled to Windows standalone .exe executable (and could be de-compiled back to .ahk source script);

And shell script for Linux/FreeBSD jobs, more specificly, BASH shell script. Because:

  • BASH is free and open-sourced;
  • Common among all Linux/BSD distributions, and is the default shell in some;
  • Could do Linux/FreeBSD-specific works.

If there is Nalakuvara for Mac OS X, Automator. Because:

  • Automator is part of Mac OS X;
  • Deals with GUI;
  • Could do Mac-specific works.

You could also do jobs with much regular languages. But please consider your effort and release size too. My opinion is: keep things simple and tiny, so that people could spread it out and work on it, with or without you.

Virtual Machine

To support different platforms, it is critical to know what exactly happened. The traditional way to do this is to prepare several systems on several machines. It is quite expensive and time-consuming. The most painful part is that you have to rebuild/reinstall them all, from time to time, in order to perform a "clean test."

Virtual technology could save your time. You could have many "guest" systems on a single "host" system. Many virtual machines give you the ability to take snapshots of current system states. So you could easily revert any system to prepared but clean states, just in a minute or two.

I used VMware Workstation. If you are looking for some free alternatives, try these:

There are many other alternatives. Just pick any suitable and handy.

For now, I have a Windows XP Professional with SP3, a Ubuntu 9.04 Desktop, and a Fedora 11 Desktop, all in my VMware Workstation (in a tiny laptop). Too bad it is impossible to run a Snow Leopard guest for I am using x86 version of Windows XP as host. (Basically a x64 guest OS has to be in a x64 host OS.)

Dive Into Opera

Playground is ready. This is where the fun begins.

Installation and Initial Phase

Let us take a closer look at what happened during Opera's installation and initial phase. On Windows, Opera installer extracts a MSI installer and runs. During the installation, users could choose where to install Opera, and whether to create shortcut icons on Desktop, Quick Launch Bar, or Start Menu. The MSI Installer language is based on Windows system environment. By default, Opera will be installed at %PROGRAMFILES%\Opera\ and the multiple users support is enabled as well.

If this is the first installation of Opera, for now, all Opera related files are in the Opera install path. At the very first time Opera is launched, several files are copied from Opera's install path to, or created at, %APPDATA%\Opera\ and %USERPROFILE%\Local Settings\Application Data\Opera\. I refer this as Opera's "initial phase." If there was another Opera installed on this system before, user setting and files usually remain at %APPDATA% and %USERPROFILE%, thus Opera does not overwrite those existent files. The initial phase might happen again, at anytime you launch Opera with user files missing.

So the best occasion to interfere with Opera is after its (whole new) installation and before its first run. Just touch files in Opera's install path and everything should work just as you imagine. This works with multiple users situation. All users get the same improved setting, and are free to tweak by their own. If you interfere after Opera's initial phase, you might have to delete all existent user profile, setting, files so that Opera will run into initial phase again, or to carefully handle files in Opera's install path, %APPDATA%, and %USERPROFILE% altogether.

On Linux, things are different. There are three types of Opera package on Linux:

  • Deb package (.deb) for Ubuntu and Debian;
  • RPM package (.rpm) for Fedora, Mandriva, RedHat, SuSE;
  • Tarball (.tar.gz) for generic Linux.

RPM and deb package require almost no user interaction to install Opera. They basically put application binary into /usr/share/opera, library into /usr/lib/opera, and two default preference setting files operaprefs_default.ini and operaprefs_fixed.ini into /etc. Tarball does the same, except that it will prompt users every path to put files, with the same default paths as RPM and deb package. Later during initial phase, Opera puts (copies or creates) user files and settings in ~/.opera.

Again, the best opportunity to interfere is just like on Windows. Otherwise you will have to deal with files in /usr/share/opera, /etc, and ~/.opera.

On FreeBSD, things are almost the same with Linux, except application binary is in /usr/local/share/opera rather than /usr/share/opera, and /usr/local/lib/opera rather than /usr/lib/opera.

Silent Installation

In order to keep users away from triggering initial phase right after installation, the best way is do not let users install Opera by themselves. This means Nalakuvara package should be able to install Opera for users.

On Windows, we could use Opera's MSI (Windows Installer) with several FOO=BAR variables in command-line, to specify a silent install. FOO is the variable name, BAR is its value; multiple variables is allowed and should be divided by a single space. The variables that could be used include:

  • CREATE_DESKTOP_ICON_REG: create shortcut icon on Desktop for all users if value is 1, not if 0;
  • CREATE_DESKTOP_ICON_REG_USR: create shortcut icon on Desktop for current user if value is 1, not if 0;
  • CREATE_QUICKLAUNCH_ICON_REG: create shortcut icon on Quick Launch Bar for all users if value is 1, not if 0;
  • CREATE_QUICKLAUNCH_ICON_REG_USR: create shortcut icon on Quick Launch Bar for current user if value is 1, not if 0;
  • CREATE_STARTMENU_ICONS: create shortcut icon on Start Menu for all users if value is 1, not if 0;
  • CREATE_STARTMENU_ICONS_REG_USR: create shortcut icon on Start Menu for current user if value is 1, not if 0;
  • ISCHECKFORPRODUCTUPDATES: check if there is updated version available if value is 1, not if 0;
  • ALLUSERS: install for all users if value is 1, not if 0;
  • LAUNCH_OPERA_ON_FINISH: launch Opera on installation finish if value is 1, not if 0;
  • SET_DEFAULT_BROWSER: register Opera as system's default web browser if value is 1, not if 0;
  • MULTI_USER_SETTING: enable multiple user setting support if value is 1, not if 0;
  • INSTALLER_LANGUAGE: specify UI language of MSI installer with language code (i.e., zh-tw means Traditional Chinese, and so on);
  • INSTALLDIR: specify where to install Opera.

By default, Opera installer will create those three shortcut icons (on Desktop, Quick Launch Bar, and Start menu), enable multiple user setting support, install Opera at %PROGRAMFILES%\Opera, set Opera as default browser, and launch Opera on finish. You could perform such a default install without user interaction by execute:

msiexec /i Opera_1060_int_Setup.msi /qn CREATE_DESKTOP_ICON_REG=1 CREATE_DESKTOP_ICON_REG_USR=1 CREATE_QUICKLAUNCH_ICON_REG=1 CREATE_QUICKLAUNCH_ICON_REG_USR=1 CREATE_STARTMENU_ICONS=1 CREATE_STARTMENU_ICONS_REG_USR=1 ISCHECKFORPRODUCTUPDATES=0 ALLUSERS=1 LAUNCH_OPERA_ON_FINISH=1 SET_DEFAULT_BROWSER=1

But we do not want Opera launched on finish. So let us change LAUNCH_OPERA_ON_FINISH to 0:

msiexec /i Opera_1060_int_Setup.msi /qn CREATE_DESKTOP_ICON_REG=1 CREATE_DESKTOP_ICON_REG_USR=1 CREATE_QUICKLAUNCH_ICON_REG=1 CREATE_QUICKLAUNCH_ICON_REG_USR=1 CREATE_STARTMENU_ICONS=1 CREATE_STARTMENU_ICONS_REG_USR=1 ISCHECKFORPRODUCTUPDATES=0 ALLUSERS=1 LAUNCH_OPERA_ON_FINISH=0 SET_DEFAULT_BROWSER=1

What if users want to specify Opera's install path? Here are some sample codes in Nalakuvara's AutoHotKey script to do so:

FileSelectFolder, OperaInstallPath, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 1, Please choose the location you would like to install Opera. Press `"Cancel`" to apply default vaule %ProgramFiles%\Opera
RunWait, msiexec /i %OperaInstaller% /qn CREATE_DESKTOP_ICON_REG=1 CREATE_DESKTOP_ICON_REG_USR=1 CREATE_QUICKLAUNCH_ICON_REG=1 CREATE_QUICKLAUNCH_ICON_REG_USR=1 CREATE_STARTMENU_ICONS=1 CREATE_STARTMENU_ICONS_REG_USR=1 ISCHECKFORPRODUCTUPDATES=0 ALLUSERS=1 LAUNCH_OPERA_ON_FINISH=0 SET_DEFAULT_BROWSER=1 INSTALLDIR="%OperaInstallPath%"

First I use FileSelectFolder to ask users to specify a folder to install Opera. Its 2nd option value, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, is a CLSID folder name for My Computer, where users starting with. The 3rd option value, 1, turns on a folder creation button. So users have to either select an existent folder or create a new folder before selecting it. Either way, the folder now exists, and its long path name is stored as %OperaInstallPath% variable.

What if users have already installed Opera before? It is a little complicated to determine whether Opera is installed, and where if it was. I check Windows registry first. If Opera is installed, there should be something at HKLM\SOFTWARE\Classes\Opera.HTML\shell\open\command. We could use AutoHotKey's RegRead to read its default value and store it as a variable:

RegRead, OperaInstallPathReg, HKLM, SOFTWARE\Classes\Opera.HTML\shell\open\command

If Opera is installed, the %OperaInstallPathReg% shoulde now be something like:

"C:\Program Files\Opera\opera.exe" "%1"

We only need the path part in this variable. So let us extract it with some simple regular expression tricks and check with AutoHotKey's IfExist:

OperaInstallPath := RegExReplace(OperaInstallPathReg, ".(.:.+)\\[Oo]pera\.exe.+$", "$1")
IfExist, %OperaInstallPath%

But even if %OperaInstallPathReg% is null, which means there is nothing at HKLM\SOFTWARE\Classes\Opera.HTML\shell\open\command, users might still have already installed Opera before but uninstalled it later, leaving something in user profile behind. So I then check those path:

IfExist, %APPDATA%\Opera

and:

IfExist, %USERPROFILE%\Local Settings\Application Data\Opera

If any of these three paths exists on the system, it means that Opera is installed before. You might like to remove old files first, or patch those old files too.

What if not only users install Opera before, but Opera is also running currently? Do not forget to close all existent Opera process in AutoHotKey script before doing anything else:

Process, Close, opera.exe

The actual code used in Nalakuvara's script is much complicated. There are other details to care about. What if users press "Cancel" while selecting Opera install path? What if users select a file rather than a folder? Check and re-check, prepare defaults and fallbacks, and make your scripts bullet proof.

These are things on Windows. What about Linux?

Deb packages invoke gdebi-gtk package manager on Ubuntu with GUI. But you could install deb packages with dpkg in command-line:

dpkg -i opera_10.00.deb

However, dpkg does not install all necessary dependencies for you. In order to do so, you have to use APT package manager's apt-get command:

apt-get -f -y install

RPM packages invoke gnome-packagekit package manager on Fedora with GUI. Again you could install RPM packages with rpm in command-line:

rpm -i --force opera-10.00.rpm

Luckily rpm deals with dependency so you do not have to do it manually.

If you fetch a tarball for generic Linux, just install it as usual way:

tar -xzf opera-10.00.tar.gz
cd opera-10.00
./install.sh

Is it that simple? No.

The main problem here is you have to be root to install packages. One way is to ask users to su as root to run the script, another is to ask users to install and setup sudo. I prefer using sudo rather than su for its security.

Ubuntu has a working sudo by default, how nice. Linux destributions using APT package manager (such as Fedora) could install and setup sudo with these commands:

su root
apt-get install sudo
visudo

Those using Easy Urpmi package manager (such as Mandriva) could do with these commands:

su root
urpmi sudo
visudo

The manual way to do so is to fetch sudo source from http://www.sudo.ws/ and then compile it. That works too. But still, users have to visudo themselves into sudoers.

FreeBSD way is to work with ports:

cd /usr/ports/www/opera
sudo make clean install

And if sudo is not usable yet, do this first:

su root
cd /usr/ports/security/sudo
make clean install
visudo

On Linux or FreeBSD, too, do not forget to close all existent Opera process before doing anything else:

killall opera

Files Location and Priority

Once Opera is installed and has not yet triggered the initial phase, what files should we touch? You might find the "Files Used by Opera for Windows" and the "Files Used by Opera for Linux, FreeBSD and Solaris" documents quite useful but a little outdated. To be short, here are our primary targets:

  • operaprefs.ini: stored program settings;
  • search.ini: default settings for the search engines available in Opera;
  • bookmarks.adr: default bookmarks file;
  • webmailproviders.ini: default settings for the web mail providers available in Opera;
  • fastforward.ini: defines what activates the Fast Forward button;
  • standard_menu.ini: Opera standard menu configuration;
  • standard_toolbar.ini: Opera standard toolbar configuration.

If you are careful enough, you might have already found that some files that have multiple instance in your system. Which one is the one? The "Configuration Priority Scheme" section from Opera's System Administrator's Handbook gives a clue. Yet this document is not detailed enough.

Studying from Ibis plus some experiments, I finally figure out the actual priority order:

  • operaprefs.ini:
    1. %SYSTEMROOT%\SYSTEM32\operaprefs_fixed.ini
    2. %APPDATA%\Opera\OPERA_DIR_NAME\operaprefs.ini
    3. %USERPROFILE%\Local Settings\Application Data\Opera\OPERA_DIR_NAME\custom\defaults\operaprefs.ini
    4. OPERA_INSTALL_PATH\custom\defaults\operaprefs.ini
    5. OPERA_INSTALL_PATH\defaults\operaprefs.ini
    6. OPERA_INSTALL_PATH\operaprefs_default.ini
  • search.ini:
    1. %APPDATA%\Opera\OPERA_DIR_NAME\search.ini
    2. OPERA_INSTALL_PATH\locale\LANGUAGE_CODE\search.ini
    3. OPERA_INSTALL_PATH\defaults\search.ini
  • bookmarks.adr:
    1. %APPDATA%\Opera\OPERA_DIR_NAME\bookmarks.adr
    2. OPERA_INSTALL_PATH\locale\LANGUAGE_CODE\bookmarks.adr
    3. OPERA_INSTALL_PATH\defaults\bookmarks.adr
  • webmailproviders.ini:
    1. OPERA_INSTALL_PATH\defaults\webmailproviders.ini
  • fastforward.ini:
    1. %USERPROFILE%\Local Settings\Application Data\Opera\OPERA_DIR_NAME\custom\defaults\fastforward.ini
    2. OPERA_INSTALL_PATH\custom\defaults\fastforward.ini
    3. OPERA_INSTALL_PATH\defaults\fastforward.ini
  • standard_menu.ini:
    1. %APPDATA%\Opera\OPERA_DIR_NAME\menu\standard_menu.ini
    2. OPERA_INSTALL_PATH\ui\standard_menu.ini
  • standard_toolbar.ini:
    1. %APPDATA%\Opera\OPERA_DIR_NAME\toolbar\standard_toolbar.ini
    2. OPERA_INSTALL_PATH\ui\standard_toolbar.ini

Allow me to explain some details:

  • OPERA_INSTALL_PATH: where you install Opera, "%PROGRAMFILES%\Opera" by default;
  • OPERA_DIR_NAME: the final part of OPERA_INSTALL_PATH, "Opera" by default;
  • LANGUAGE_CODE: the UI language that Opera is currently running with. "zh-tw" for Traditional Chinese, "zh-cn" for Simplified Chinese, "en" for English, etc;
  • %USERPROFILE%\Local Settings\Application Data\Opera\OPERA_DIR_NAME\custom\defaults\* are copied from OPERA_INSTALL_PATH\custom\defaults\* during initial phase;
  • %PROGRAMFILES% is a Windows environment variable, usually "C:\Program Files";
  • %APPDATA% is a Windows environment variable, usually "%USERPROFILE%\Application Data";
  • %USERPROFILE% is a Windows environment variable, usually "C:\Documents and Settings\USER_NAME" where USER_NAME is the Windows user name of current user;
  • %SYSTEMROOT% is a Windows environment variable, usually "C:\WINDOWS";
  • standard_menu.ini and standard_toolbar.ini will not be overthrown by higher priority ones. They will appear together and allow users to switch between them.

It is quite tricky and complicated to decide which file to work on. Doing files with priority too high causes users to be unable to change their own preferences; files with priority too low could not make things work since everything you do is overthrown as some of these files could be locale-based. So you could deliver different tweak to users using different locales. This makes great sense. Too bad that not every part works this way.

In the end, I picked up these files:

  • OPERA_INSTALL_PATH\custom\defaults\operaprefs.ini
  • OPERA_INSTALL_PATH\locale\zh-tw\search.ini
  • OPERA_INSTALL_PATH\locale\zh-cn\search.ini
  • OPERA_INSTALL_PATH\locale\en\search.ini
  • OPERA_INSTALL_PATH\locale\zh-tw\bookmarks.adr
  • OPERA_INSTALL_PATH\locale\zh-cn\bookmarks.adr
  • OPERA_INSTALL_PATH\locale\en\bookmarks.adr
  • OPERA_INSTALL_PATH\defaults\webmailproviders.ini
  • OPERA_INSTALL_PATH\custom\defaults\fastforward.ini
  • OPERA_INSTALL_PATH\ui\standard_menu.ini
  • OPERA_INSTALL_PATH\ui\standard_toolbar.ini

Opera on Linux is basically the same, except operaprefs_fixed.ini and operaprefs_default.ini both located at /etc (on FreeBSD, /usr/local/etc).

Tweak Defaults

First thing first. Most of the features users want is available through changing Opera's setting:

[User Prefs]
Feature opera:config Link Opera Default Nalakuvara Tweak
Enable Mouse Gesture
(Note: default to 1 since Opera 10.50)
opera:config#UserPrefs|EnableGesture 0 1
Enable All Drag & Drop Feature opera:config#UserPrefs|EnableDrag 247 255
Double Click on Tab to Close It opera:config#UserPrefs|DoubleclicktoCloseTab 0 1
Open New Tab/Window Rather Than Re-use Current One opera:config#UserPrefs|NewWindow 0 1
Open New Tab/Window in Background
(Note: does not work anymore since Opera 10.50)
opera:config#UserPrefs|OpenNewWindowinBackground 0 1
Show Panel Toggle Area at the Window Edge opera:config#UserPrefs|Showpaneltoggle 0 1
Open Dragged Link in Background Teb/Window
(Note: added since Opera 10.60)
opera:config#UserPrefs|OpenDraggedLinkInBackground 0 1
[Fonts]
(Note: modifing this session does not needed anymore since Opera 10.60)
Feature opera:config Link Opera Default Nalakuvara Tweak
Browser Dialog Fonts for Traditional Chinese opera:config#Fonts|Dialog 15,4,0,0,0,0,SimSun 12,4,0,0,0,0,新細明體
Browser Menu Fonts for Traditional Chinese opera:config#Fonts|Menu 15,4,0,0,0,0,SimSun 12,4,0,0,0,0,新細明體
Browser Panel Fonts for Traditional Chinese opera:config#Fonts|Panel 15,4,0,0,0,0,SimSun 12,4,0,0,0,0,新細明體
Browser Toolbar Fonts for Traditional Chinese opera:config#Fonts|Toolbar 15,4,0,0,0,0,SimSun 12,4,0,0,0,0,新細明體
Browser Tooltip Fonts for Traditional Chinese opera:config#Fonts|Tooltip 15,4,0,0,0,0,SimSun 12,4,0,0,0,0,新細明體
[Network]
Feature opera:config Link Opera Default Nalakuvara Tweak
(HTTP) Accept Traditional Chinese and English, Avoid Simplified Chinese opera:config#Network|HTTPAcceptLanguage zh-TW,zh;q=0.9,en;q=0.8 zh-tw,en;q=0.9
Do Not Check Local Host Name While Entering Invalid URL opera:config#Network|CheckLocalHostName 1 0
Do Not Append Host Name Prefix/Postfix While Entering Invalid URL opera:config#Network|EnableHostNameExpansion 1 0
Use Web (Search Engine) to Lookup Host Name While Entering Invalid URL opera:config#Network|EnableHostNameWebLookup 0 1
The Web Search URL to Lookup Host Name opera:config#Network|HostNameWebLookupAddress http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8

The reason to change Browser fonts is that SimSun looks good in Simplified Chinese, but horrible in Traditional Chinese. We also have to tweak default HTTP Accept languages to rule out zh, otherwise some sites wrongly send Simplified Chinese content to Taiwanese users. Traditional Chinese and Simplified Chinese are more like two different languages; treating one as the subset of the other one causes troubles.

Host Name Expansion (append prefix/postfix to invalid host name automatically) is also disabled. Because Traditional Chinese host name such as http://網頁設計.tw/ is still not popular in Taiwan, enabling this expansion often brings users to docked page of domain name retailers.

We could do these for users by editing OPERA_INSTALL_PATH\custom\defaults\operaprefs.ini:

Opera Preferences version 2.1
; Do not edit this file while Opera is running
; This file is stored in UTF-8 encoding

[User Prefs]
Enable Gesture=1
Enable Drag=255
Doubleclick to Close Tab=1
New Window=1
Open New Window in Background=1
Show panel toggle=1

[Fonts]
Menu=12,4,0,0,0,0,新細明體
Toolbar=12,4,0,0,0,0,新細明體
Dialog=12,4,0,0,0,0,新細明體
Panel=12,4,0,0,0,0,新細明體
Tooltip=12,4,0,0,0,0,新細明體

[Network]
HTTP Accept Language=zh-tw,en;q=0.9
Check Local HostName=0
Enable HostName Expansion=0
Enable HostName Web Lookup=1
HostName Web Lookup Address=http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8

新細明體 (MingLiU) is the default system font on Traditional Chinese version of Windows, and not available on Linux/FreeBSD. There is also a bug on these platforms of Opera, causing Traditional Chinese and Simplified Chinese fonts to be mixed up in web contents, and resulting in inconsistency and ugly display. The workaround is to use "AR PL UMing TW MBE" and "AR PL UKai TW MBE" for browser UI and default (preferred) fonts:

[Fonts]
Feature opera:config Link Opera Default Nalakuvara Tweak
Browser Dialog Fonts for Traditional Chinese opera:config#Fonts|Dialog 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Browser Menu Fonts for Traditional Chinese opera:config#Fonts|Menu 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Browser Panel Fonts for Traditional Chinese opera:config#Fonts|Panel 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Browser Toolbar Fonts for Traditional Chinese opera:config#Fonts|Toolbar 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Browser Tooltip Fonts for Traditional Chinese opera:config#Fonts|Tooltip 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Web Page Normal Text Font opera:config#Fonts|Normal 16,4,0,0,0,0,Nimbus Roman No9 L [urw] 16,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Web Page <pre> Text Font opera:config#Fonts|PRE 16,4,0,0,0,0,Nimbus Mono L [urw] 16,4,0,0,0,0,AR PL UKai TW MBE [unknown]
[Preferred fonts]
Feature opera:config Link Opera Default Nalakuvara Tweak
Preferred Traditional Chinese Font N/A Nimbus Sans L [urw] AR PL UMing TW MBE [unknown]
[Preferred fonts monospace]
Feature opera:config Link Opera Default Nalakuvara Tweak
Preferred Traditional Chinese Monospace Font N/A Nimbus Mono L [urw] AR PL UKai TW MBE [unknown]
[CSS Generic Font Family]
Feature opera:config Link Opera Default Nalakuvara Tweak
Generic CSS Sans-Serif Font Family opera:config#CSSGenericFontFamily|Sans-Serif Nimbus Roman No9 L [urw] AR PL UMing TW MBE [unknown]
Generic CSS Serif Font Family opera:config#CSSGenericFontFamily|Serif Nimbus Mono L [urw] AR PL UKai TW MBE [unknown]

Which results the following /usr/share/opera/operadefaults.ini:

; Put any default settings here that are overridable by users

[User Prefs]
Enable Gesture=1
Enable Drag=255
Doubleclick to Close Tab=1
New Window=1
Open New Window in Background=1
Show panel toggle=1
NavigationBar Alignment=2
NavigationBar Auto Alignment=1

[Network]
HTTP Accept Language=zh-tw,en;q=0.9
Check Local HostName=0
Enable HostName Expansion=0
Enable HostName Web Lookup=1
HostName Web Lookup Address=http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8

[Fonts]
Menu=14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Toolbar=14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Dialog=14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Panel=14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Tooltip=14,4,0,0,0,0,AR PL UMing TW MBE [unknown]
Normal=16,4,0,0,0,0,AR PL UMing TW MBE [unknown]
PRE=16,4,0,0,0,0,AR PL UKai TW MBE [unknown]

[Preferred fonts]
59=AR PL UMing TW MBE [unknown]

[Preferred fonts monospace]
59=AR PL UKai TW MBE [unknown]

[CSS Generic Font Family]
Sans-Serif=AR PL UMing TW MBE [unknown]
Serif=AR PL UKai TW MBE [unknown]

This is just a workaround, not a solution, for Ming (明體) is not a Sans-Serif font. Using this setting, web pages in English do not looks well. Limited by Linux's default fonts availability, Nalakuvara hardly tweaks better.

Some Linux distributions are more lucky. Ubuntu has two Traditional Chinese Gothic font (文泉驛等寬正黑 and 文泉驛正黑, monospace and not) installed by default, which are Sans-Serif, and better in quality. That is why Nalakuvara provides an alternative default for Ubuntu users:

[Fonts]
Feature opera:config Link Opera Default Nalakuvara Tweak
Browser Dialog Fonts for Traditional Chinese opera:config#Fonts|Dialog 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,文泉驛正黑 [unknown]
Browser Menu Fonts for Traditional Chinese opera:config#Fonts|Menu 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,文泉驛正黑 [unknown]
Browser Panel Fonts for Traditional Chinese opera:config#Fonts|Panel 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,文泉驛正黑 [unknown]
Browser Toolbar Fonts for Traditional Chinese opera:config#Fonts|Toolbar 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,文泉驛正黑 [unknown]
Browser Tooltip Fonts for Traditional Chinese opera:config#Fonts|Tooltip 12,4,0,0,0,0,Nimbus Sans L [urw] 14,4,0,0,0,0,文泉驛正黑 [unknown]
Web Page Normal Text Font opera:config#Fonts|Normal 16,4,0,0,0,0,Nimbus Roman No9 L [urw] 16,4,0,0,0,0,文泉驛正黑 [unknown]
Web Page <pre> Text Font opera:config#Fonts|PRE 16,4,0,0,0,0,Nimbus Mono L [urw] 16,4,0,0,0,0,文泉驛等寬正黑 [unknown]
[Preferred fonts]
Feature opera:config Link Opera Default Nalakuvara Tweak
Preferred Traditional Chinese Font N/A Nimbus Sans L [urw] 文泉驛正黑 [unknown]
[Preferred fonts monospace]
Feature opera:config Link Opera Default Nalakuvara Tweak
Preferred Traditional Chinese Monospace Font N/A Nimbus Mono L [urw] 文泉驛等寬正黑 [unknown]
[CSS Generic Font Family]
Feature opera:config Link Opera Default Nalakuvara Tweak
Generic CSS Sans-Serif Font Family opera:config#CSSGenericFontFamily|Sans-Serif Nimbus Roman No9 L [urw] 文泉驛正黑 [unknown]
Generic CSS Serif Font Family opera:config#CSSGenericFontFamily|Serif Nimbus Mono L [urw] AR PL UKai TW MBE [unknown]

So Ubuntu users get following /usr/share/opera/operadefaults.ini:

; Put any default settings here that are overridable by users

[User Prefs]
Enable Gesture=1
Enable Drag=255
Doubleclick to Close Tab=1
New Window=1
Open New Window in Background=1
Show panel toggle=1
NavigationBar Alignment=2
NavigationBar Auto Alignment=1

[Network]
HTTP Accept Language=zh-tw,en;q=0.9
Check Local HostName=0
Enable HostName Expansion=0
Enable HostName Web Lookup=1
HostName Web Lookup Address=http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8

[Fonts]
Menu=14,4,0,0,0,0,文泉驛正黑 [unknown]
Toolbar=14,4,0,0,0,0,文泉驛正黑 [unknown]
Dialog=14,4,0,0,0,0,文泉驛正黑 [unknown]
Panel=14,4,0,0,0,0,文泉驛正黑 [unknown]
Tooltip=14,4,0,0,0,0,文泉驛正黑 [unknown]
Normal=16,4,0,0,0,0,文泉驛正黑 [unknown]
PRE=16,4,0,0,0,0,文泉驛等寬正黑 [unknown]

[Preferred fonts]
59=文泉驛正黑 [unknown]

[Preferred fonts monospace]
59=文泉驛等寬正黑 [unknown]

[CSS Generic Font Family]
Sans-Serif=文泉驛正黑 [unknown]
Serif=AR PL UKai TW MBE [unknown]

It is very important to ensure UTF-8 encoding is used in the .ini files, especially when dealing with preferences in Traditional Chinese such as font names.

Opera by default includes some web mail service providers with OPERA_INSTALL_PATH\defaults\webmailproviders.ini. By editing this file, we could comment out those unpopular, and add some more popular for Taiwanese users:

Opera Preferences version 2.1 
; Do not edit this file while Opera is running 
; This file is stored in UTF-8 encoding 
; %t = to 
; %j = subject 
; %m = body 
; %k = cc 
; %l = bcc 
; %s = full mailto URI
; i.e., %s = to=%t&subject=%j&body=%m&cc=%k&bcc=%l

;[Yandex]
;ID=4
;URL=http://mail.yandex.ru/compose?mailto=%s
;ICON=http://img.yandex.net/i/favicon.ico

;[Fastmail]
;ID=5
;URL=http://www.fastmail.fm/action/compose/?mailto=%s
;ICON=http://www.fastmail.fm/favicon.ico

[Opera Web Mail]
ID=6
URL=http://mymail.operamail.com/scripts/mail/Outblaze.mail?compose=1&did=1&a=1&to=%t&subject=%j&body=%m&cc=%k
ICON=http://www.opera.com/favicon.ico

;[Mail.ru] 
;ID=7 
;URL=http://win.mail.ru/cgi-bin/sentmsg?To=%t&CC=%k&BCC=%l&Subject=%j&Body=%m 
;ICON=http://img.imgsmail.ru/r/favicon.ico

[Gmail - HTML5]
ID=8
URL=https://mail.google.com/mail/?extsrc=mailto&url=%s
ICON=https://mail.google.com/favicon.ico

[Gmail]
ID=9
URL=https://mail.google.com/mail/?compose=1&view=cm&fs=1&to=%t&su=%j&body=%m&cc=%k&bcc=%l
ICON=https://mail.google.com/favicon.ico

[Hotmail]
ID=10
URL=http://mail.live.com/mail/EditMessageLight.aspx?n=&to=%t&cc=%k&subject=%j&body=%m&bcc=%l
ICON=http://mail.live.com/favicon.ico

[Ymail - Generic]
ID=11
URL=http://compose.mail.yahoo.com/?To=%t&Subj=%j&Body=%m&Cc=%k&Bcc=%l
ICON=http://mail.yahoo.com/favicon.ico

[Ymail - Classic Compose + New UI]
ID=12
URL=http://us.mg1.mail.yahoo.com/mc/compose?ymv=0&body=%m&Subj=%j&to=%t&cc=%k&bcc=%l
ICON=http://mail.yahoo.com/favicon.ico

[Ymail - New UI + Blocking Workaround]
ID=13
URL=http://us.mg1.mail.yahoo.com/dc/launch?sysreq=ignore&action=compose&login=1&To=%t&Subj=%j&Cc=%k&Bcc=%l&Body=%m
ICON=http://mail.yahoo.com/favicon.ico

[Mail2000]
ID=14
URL=http://www.mail2000.com.tw/cgi-bin/genMail.pl?adr=%t&content=%m&subject=%j
ICON=http://www.mail2000.com.tw/favicon.ico

[PChome Mail]
ID=20
URL=http://mail.pchome.com.tw/compose_content?MailTo=%t&MailSubject=%j&MailCc=%k&MailBcc=%l&text2=%m
ICON=http://www.pchome.com.tw/favicon.ico

[Webmail@URL (wm1)]
ID=21
URL=http://wm1.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm2)]
ID=22
URL=http://wm2.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm3)]
ID=23
URL=http://wm3.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm4)]
ID=24
URL=http://wm4.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm5)]
ID=25
URL=http://wm5.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm6)]
ID=26
URL=http://wm6.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm7)]
ID=27
URL=http://wm7.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm8)]
ID=28
URL=http://wm8.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm9)]
ID=29
URL=http://wm9.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

[Webmail@URL (wm10)]
ID=30
URL=http://wm10.url.com.tw/src/compose.php?mailbox=INBOX&startMessage=1&send_to=%t&sed_to_cc=%k&send_to_bcc=%l&subject=%j&body=%m
ICON=http://www.url.com.tw/images/url.ico

Nalakuvara adapts a modified OPERA_INSTALL_PATH\custom\defaults\fastforward.ini from Ibis, which adds more strings to trigger Fast Forward button, then adds some additional strings used in Taiwan. Here is part of it:

;Chinese (traditional and simplified)
前进
继续
翻页
下页
下頁
下篇
后页
后页>
往后>>
下一頁
下一页=101
下一页>
下一页>>
下一个
下一张
下一张 >
下一幅
下一幅 >
下一章
下一节
下一節
下一篇
后一页=90
下一步
翻下页
翻下頁
看下一页
下一页(快捷键→)
"[下頁]"
"[下页]"
"[继续]"
"[下一頁]"
"[下一页]"
"[翻下頁]"
"[翻下页]"
下一張 (C)
下一頁 (C)

Default bookmarks and searches could also be modified. Since these two default files could be locale-based, it is much reasonable to so that way. For example, adding more searches in OPERA_INSTALL_PATH\locale\zh-tw\search.ini only takes effect while using Traditional Chinese UI of Opera:

[Search Engine 1]
UNIQUEID=7A8CADE6677811DDBA4B5E9D55D89593
Name=
URL=http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8
ICON=http://redir.opera.com/favicons/google/favicon.ico
Query=
Key=g
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Verbtext=0
Position=-1
Nameid=17171
UseTLD=1

[Search Engine 2]
UNIQUEID=C62302A2FBB8E8469557BD47409F8747
Name=Yahoo!奇摩搜尋
Verbtext=0
URL=http://tw.search.yahoo.com/search?ei=&fr=sfp&fr2=&p=%s&_adv_prop=web&fl=0&vl=0&vf=all&vd=all&iscqry=
ICON=http://tw.search.yahoo.com/favicon.ico
Query=
Key=ys
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 3]
UNIQUEID=8FF7B2066FB77449B62B04D1D40EF8F8
Name=Bing
Verbtext=0
URL=http://www.bing.com/search?q=%s&go=&form=QBLH&filt=all
ICON=http://www.bing.com/favicon.ico
Query=
Key=b
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 4]
UNIQUEID=AE41FF7A5FC011DDAE47DBEF55D89593
Name=維基百科
URL=http://zh.wikipedia.org/wiki/Special:Search?search=%s
ICON=http://redir.opera.com/favicons/wikipedia/favicon.ico
Query=
Key=w
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Verbtext=0
Position=-1

[Search Engine 26]
UNIQUEID=17488DC9AE770545B642C790CAB3C9D2
Name=Internet Archive
Verbtext=0
URL=http://web.archive.org/web/*%s
ICON=http://www.archive.org/images/logo-16.jpg
Query=
Key=ia
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 27]
UNIQUEID=829D47CC797B29459E6F38E927BABCF2
Name=全國法規資料庫法規名稱檢索
Verbtext=0
URL=http://law.moj.gov.tw/Scripts/SimpleQ.asp?rb=lname&K1=%s
Query=
Key=jn
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 28]
UNIQUEID=B980F29D8FEF9A4D896C5D035DF1270D
Name=全國法規資料庫法條內容檢索
Verbtext=0
URL=http://law.moj.gov.tw/Scripts/SimpleQ1.asp?K1=%s&K2=&K3=&K4=&Fusekey=%B1%60%A5%CE%BBy%B7J&rb=la
Query=
Key=j
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 29]
UNIQUEID=F290D3865FC011DD83CDD4F355D89593
Name=
URL=http://redir.opera.com/amazon/?q=%s
ICON=http://redir.opera.com/favicons/amazon/favicon.ico
Query=
Key=z
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Verbtext=0
Nameid=69678
Position=-1

[Search Engine 30]
UNIQUEID=82EB048A5FCE11DDAFCFE0AA56D89593
Name=
URL=http://redir.opera.com/ebay/?q=%s
ICON=http://redir.opera.com/favicons/ebay/favicon.ico
Query=
Key=e
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=0
Verbtext=0
Position=-1
Nameid=69679

[Search Engine 31]
UNIQUEID=2C42B3DE30288847A11B871C19A3D7E2
Name=PChome線上購物
Verbtext=0
URL=http://shopping.pchome.com.tw/?m=search&f=doSearch&STYPE=&target=%s&Submit=%A7%E4%B0%D3%AB%7E
ICON=http://shopping.pchome.com.tw/favicon.ico
Query=
Key=pch
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 32]
UNIQUEID=6EA8C2D1619F7442827906A8D25E53B0
Name=露天拍賣
Verbtext=0
URL=http://search.ruten.com.tw/search/s000.php?searchfrom=indexbar&k=%s&t=0
ICON=http://www.ruten.com.tw/favicon.ico
Query=
Key=rb
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 33]
UNIQUEID=77C25A05B0E75A4B81DBE19E88644DC5
Name=Yahoo!奇摩拍賣
Verbtext=0
URL=http://tw.search.bid.yahoo.com/search/ac?ei=BIG-5&p=%s
ICON=http://tw.bid.yahoo.com/favicon.ico
Query=
Key=yb
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 34]
UNIQUEID=A56370F8D5684A4A82184AA4B796FFCD
Name=射手網字幕
Verbtext=0
URL=http://shooter.cn/sub/?searchword=%s&x=0&y=0
ICON=http://shooter.cn/favicon.ico
Query=
Key=sub
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 35]
UNIQUEID=F182FB89FD59FB4BAB0CD8C71E2C3234
Name=海盜灣 BT
Verbtext=0
URL=http://thepiratebay.org/search/%s/0/99/0
ICON=http://thepiratebay.org/favicon.ico
Query=
Key=tpb
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 36]
UNIQUEID=016F899833096540B36B4F52569C723A
Name=Mininova BT
Verbtext=0
URL=http://www.mininova.org/search/?search=%s
ICON=http://mnstat.com/images/favicon.ico
Query=
Key=m
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

[Search Engine 37]
UNIQUEID=AF5D5F3752D1F84BB2F3D54F9EDD4999
Name=isoHunt BT
Verbtext=0
URL=http://isohunt.com/torrents.php?ihq=%s
ICON=http://isohunt.com/favicon.ico
Query=
Key=ih
Is post=0
Has endseparator=0
Encoding=big5
Search Type=0
Position=-1
Nameid=0
Deleted=0

Above are part of modified OPERA_INSTALL_PATH\locale\zh-tw\search.ini in Nalakuvara, featureing more popular searches among Taiwanese users. If you use English or Simplified Chinese UI, you will not see these. So it is quite fine to use Nalakuvara in multiple users situation. search.ini does more than just defining default searches. I will talk about this later in "Altering Menus and Toolbars" section.

Default bookmarks are locale-based, too. The OPERA_INSTALL_PATH\locale\zh-tw\bookmarks.adr for Traditional Chinese UI users strips unpopular entries, and adds important Traditional Chinese resource about Opera:

Opera Hotlist version 2.0
Options: encoding = utf8, version=3

#FOLDER
	ID=11
	NAME=回收桶
	TRASH FOLDER=YES
	UNIQUEID=4E1601F6F30511DB9CA51FD19A7AAECA

-

#FOLDER
	ID=12
	NAME=Opera
	UNIQUEID=826CF25AF11C491899711FC93513A4F4

#URL
	ID=13
	NAME=Download Opera
	URL=http://www.opera.com/download/
	VISITED=1252173878
	UNIQUEID=6346265318C548DC831B7DF6D8EBB577

#URL
	ID=14
	NAME=My Opera Community
	URL=http://my.opera.com/
	ON PERSONALBAR=YES
	PERSONALBAR_POS=1
	UNIQUEID=6081957B53904ED6BAD072D157C8D408
	ICONFILE=my.opera.com.ico

#URL
	ID=15
	NAME=Opera Web Mail
	URL=http://www.operamail.com/
	UNIQUEID=CF79297898B24364A89ED412D9B43B89

#URL
	ID=16
	NAME=Support Desk
	URL=http://www.opera.com/support/
	VISITED=1252173859
	UNIQUEID=BDBBEF1FCB2844A980752782E0D9670C

#URL
	ID=17
	NAME=Opera Nalakuvara 三太子
	URL=http://Jedi.org/opera/
	CREATED=1252173550
	DESCRIPTION=
	UNIQUEID=D4A427CF2F790642909162DED1FCA7D8

#URL
	ID=18
	NAME=Opera 官方論壇正體中文版
	URL=http://my.opera.com/tradchinese/forums/
	CREATED=1252173758
	DESCRIPTION=
	UNIQUEID=115491135268A74C8E5B2E60C98C13C2

#URL
	ID=19
	NAME=Opera第一手最新消息繁體中文版
	URL=http://my.opera.com/ting0619/blog/
	CREATED=1252173839
	DESCRIPTION=
	UNIQUEID=AFC07AA46717884BB243A755BD59228A

Please also notice that bookmarks.adr has to be in UTF-8 encoding, too.

And last, Opera has a built-in function to fake User Agent string. This is because some web sites reject Opera for no reason. Those sites in fact work well in Opera, but they just do not accept Opera's User Agent string. Once Opera fakes itself as Firefox or Internet Explorer, everything goes fine.

Each time Opera is running, it checks and downloads an up-to-dated fake list to %APPDATA%\Opera\OPERA_DIR_NAME\override_downloaded.ini. Editing this file is a waste of time, since it is always overwritten. All manually site preferences (including fake User Agent string) are stored at %APPDATA%\Opera\OPERA_DIR_NAME\override.ini. That is our true target:

Opera Preferences version 2.1
; Do not edit this file while Opera is running
; This file is stored in UTF-8 encoding

[Overrides]
soweb.kcg.gov.tw
web2.cc.ntu.edu.tw

[soweb.kcg.gov.tw]
User Agent|Spoof UserAgent ID=5

[web2.cc.ntu.edu.tw]
User Agent|Spoof UserAgent ID=5

The numeric value of User Agent|Spoof UserAgent ID means:

  • 1: identify as Opera, i.e., Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.2.15 Version/10.00
  • 2: identify as Firefox, i.e., Mozilla/5.0 (Windows NT 5.1; U; zh-tw; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 10.00
  • 3: identify as Internet Explorer, i.e., Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; zh-tw) Opera 10.00
  • 4: fake as Firefox, i.e., Mozilla/5.0 (Windows NT 5.1; U; zh-tw; rv:1.8.1) Gecko/20061208 Firefox/2.0.0
  • 5: fake as Internet Explorer, i.e., Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; zh-tw)

Those listed sites are from user reports. I will talk about this later in the "Feedback" section.

3rd Party Components

And there are somethings Opera could not do by itself. As mentioned in "Guidelines" section before, it has no choice but use 3rd party components to achieve some functions. There are several parts we could plug these components into Opera:

  • User CSS: put in OPERA_INSTALL_PATH\styles\user\ by default;
  • User JavaScript: disabled by default;
  • Plug-In: put in OPERA_INSTALL_PATH\program\plugins\ by default;
  • Java Applet: requires Java Runtime Environment.

User CSS has minor impacts. CSS, by definition, means Cascade Style Sheets. Opera is the one browser that implements CSS web standard cascade-like. Users could apply multiple user CSS cascading. With the power of CSS, Opera has already achieved some leading functions such as Fit Width. Opera is also the one browser that implements all CSS3 selectors. Opera@USB, for example, includes some handy advertisement blocking functions purely via CSS.

User CSS could be applied or disapplied on demand through View menu in Opera. Other ways, such as through Toolbar buttons, are, however, quite difficult. The Opera's internal command "Select user CSS file" targets particular CSS file by its order in the User CSS path. In order to make buttons using User CSS on demand, we have to take control of particular CSS files order.

On Windows, files are arranged by its filename. I take CSS files from Opera@USB, rename them to 000_Antiflash.css and 000_bantiad.css to make sure they are the first two files among all. On Linux or FreeBSD, however, do not work that way. So sad these buttons work only on Windows. I will talk about these buttons later, in "Altering Menus and Toolbars" section.

000_Antiflash.css blocks all Flash content in a web page:

@charset "UTF-8";
/*
Name: Flash Blocker
Version: 1 08.2005
Beschreibung: Flash und Shockwave Blocker Version 12.06
*/

object[classid="clsid:D27CDB6E-aE6D-11cf-96B8-444553540000"],
object[classid="clsid:166B1BCA-3F9C-11CF-8075-444553540000"],
object[type="application/x-shockwave-flash"],
embed[type="application/x-shockwave-flash"],
embed[type="application/x-director"],
embed[quality]
embed[src$=".swf"]
{display: none !important;}

000_bantiad.css blocks particular size of images in a web page:

@charset "UTF-8";
/*
Name: Grafik Blocker
Version: 1
Beschreibung: Grafik Blocker
*/

[height="60"][width="468"], [height="60px"][width="468px"],
[height="31"][width="88"], [height="31px"][width="88px"],
[height="336"][width="280"], [height="336px"][width="280px"],
[height="300"][width="250"], [height="300px"][width="250px"],
[height="250"][width="250"], [height="250px"][width="250px"],
[height="400"][width="240"], [height="400px"][width="240px"],
[height="120"][width="240"], [height="120px"][width="240px"],
[height="60"][width="234"], [height="60px"][width="234px"],
[height="150"][width="180"], [height="150px"][width="180px"],
[height="600"][width="160"], [height="600px"][width="160px"],
[height="125"][width="125"], [height="125px"][width="125px"],
[height="600"][width="120"], [height="600px"][width="120px"],
[height="90"][width="120"], [height="90px"][width="120px"],
[height="60"][width="120"], [height="60px"][width="120px"]
{display: none !important;}

This is an excellent demonstration of CSS attribution selector.

User JavaScript extends more possibility but might bring compatibility and security issue, and is disabled by default. To enable User JavaScript feature, tweak following preferences:

[User Prefs]
Feature opera:config Link Opera Default Nalakuvara Tweak
Enable User JavaScript opera:config#UserPrefs|UserJavaScript 0 1
Always Load User JavaScript Even on Web Pages Without <script> opera:config#UserPrefs|AlwaysLoadUserJavaScript 0 1
Do Not Enable User JavaScript on HTTPS Connection opera:config#UserPrefs|UserJavaScriptonHTTPS 0 0
Specify User JavaScript Directory opera:config#UserPrefs|UserJavaScriptFile userjs

For example, OPERA_INSTALL_PATH\custom\defaults\operaprefs.ini on Windwos should be:

Opera Preferences version 2.1
; Do not edit this file while Opera is running
; This file is stored in UTF-8 encoding

[User Prefs]
Enable Gesture=1
Enable Drag=255
Doubleclick to Close Tab=1
New Window=1
Open New Window in Background=1
Show panel toggle=1
User JavaScript=1
Always Load User JavaScript=1
User JavaScript on HTTPS=0
User JavaScript File=userjs

[Fonts]
Menu=12,4,0,0,0,0,新細明體
Toolbar=12,4,0,0,0,0,新細明體
Dialog=12,4,0,0,0,0,新細明體
Panel=12,4,0,0,0,0,新細明體
Tooltip=12,4,0,0,0,0,新細明體

[Network]
HTTP Accept Language=zh-tw,en;q=0.9
Check Local HostName=0
Enable HostName Expansion=0
Enable HostName Web Lookup=1
HostName Web Lookup Address=http://www.google.com/search?q=%s&sourceid=opera&num=%i&ie=utf-8&oe=utf-8

User JavaScript on HTTPS remains disabled for security concerns. If you have to enable this preference, please, rethink again, and warn users explicitly too.

User JavaScript File could be either absolute or relative path. It is wise to let users choose where to put their own user JavaScript files. However, it is convenient to predefine a relative path here. The tricky part here is that working directory is different on Windows and on Linux/FreeBSD. On Windows, Opera's working directory is where opera.exe is located, i.e., OPERA_INSTALL_PATH. On Linux or FreeBSD, Opera's working directory is user's home directory, i.e., ~. The User JavaScript File relative path is related to Opera's working directory, which means userjs makes OPERA_INSTALL_PATH\userjs\ on Windows, ~/userjs/ on Linux or FreeBSD.

Nalakuvara chooses User JavaScript based on guidelines carefully. Here is my final list:

The pure-JavaScript version of AdBlock Plus uses CSS attribution selector and optional CSS3 nth-child selector to target web elements to block. All "blocker" CSS rules are stored in cookies. All AdBlock Plus functions could be accessed via Toolbar buttons, which will be discussed in "Altering Menus and Toolbars" section, and hotkeys:

  • Alt-Shift-B: block web elements with CSS3 nth-child selector;
  • Alt-Shift-W: block web elements without CSS3 nth-child selector;
  • Alt-Shift-U: revert previous blocked web elements;
  • Alt-Shift-L: revert last blocked web elements;
  • Alt-Shift-E: edit blocker CSS rules manually.

Autosizer 2 lets users click on large images to resize it to fit browser window size. Click again to restore its original size. It also uses cookies to store this resize setting for each image.

CustomizeGoogle uses a separate customizegoogle_prefs.js to adjust its behavior. Here is the predefined option in Nalakuvara:

Google Web Search /* webtab */
Options Description Nalakuvara's Predefined Value
web.remove-ads Remove Advertisements true
web.search-links Add Links from Other Search Engines false
web.suggest Enable Google Suggest true
web.focus Set Input Focus at Search Field false
web.counter Add Counter on Search Results true
web.filter Enable Filter Rules false
web.history Add Links to WayBackMachine.org true
web.removeclicktrack Remove Google's Click Track true
web.auto-page Display Next Search Results Continuous false
web.favicons Display Favicons of Search Results true
Google Images Search /* imagestab */
Options Description Nalakuvara's Predefined Value
images.image-links Add Links from Other Images Search Engines false
images.rewrite-links Rewrite Links of Original Images and Web Pages true
images.auto-page Display Next Search Results Continuous false
Google Groups /* groupstab */
Options Description Nalakuvara's Predefined Value
groups.remove-ads Remove Advertisements true
Google News /* newstab */
Options Description Nalakuvara's Predefined Value
news.news-links Add Links from Other News Search Engines false
news.filter Enable Filter Rules false
news.removeclicktrack Remove Google's Click Track true
Google Products Search /* froogletab */
Options Description Nalakuvara's Predefined Value
froogle.remove-ads Remove Advertisements true
froogle.products-links Add Links from Other Products Search Engines false
Google Answers /* answerstab */
Options Description Nalakuvara's Predefined Value
answers.remove-ads Remove Advertisements true
Google Print /* printtab */
Options Description Nalakuvara's Predefined Value
print.remove-ads Remove Advertisements true
print.restore-menu Restore Right-Click Menu true
print.book-links Add Links from Other Book Sites false
GMail /* gmailtab */
Options Description Nalakuvara's Predefined Value
gmail.remove-ads Remove Advertisements true
gmail.secure Secure Mode (Switch to https:// Connection) true
gmail.hidespam Hide Spam-Counter false
gmail.hidechat Hide "Quick Contacts Box" false
gmail.hideinvite Hide "Invite Box" true
gmail.monospace Display Mail Content Using Monospace Font false
Google Calendar /* calendartab */
Options Description Nalakuvara's Predefined Value
calendar.secure Secure Mode (Switch to https:// Connection) true
Google Local /* localtab */
Options Description Nalakuvara's Predefined Value
local.remove-ads Remove Advertisements true
Google Docs & Spreadsheets /* docstab */
Options Description Nalakuvara's Predefined Value
docs.secure Secure Mode (Switch to https:// Connection) true
Google Videos Search /* videotab */
Options Description Nalakuvara's Predefined Value
video.video-links Add Links from Other Videos Search Engines false
Google Reader /* readertab */
Options Description Nalakuvara's Predefined Value
reader.secure Secure Mode (Switch to https:// Connection) false
Google Cache /* cachetab */
Options Description Nalakuvara's Predefined Value
cache.continue Rewrite Links to Google Cached true
Google Blog Search /* blogtab */
Options Description Nalakuvara's Predefined Value
blogs.blog-links Add Links from Other Blogs Search Engines false
blogs.removeclicktrack Remove Google's Click Track true
Google Web History /* historytab */
Options Description Nalakuvara's Predefined Value
history.secure Secure Mode (Switch to https:// Connection) true
Privacy /* privacytab */
Options Description Nalakuvara's Predefined Value
misc.anonymizeUID Anonymous Google cookie UID false
misc.removeGoogleAnalytics Remove Google Analytics true
Preferences /* Preferencestab */ (cookies.enableDefaultPreferences has to be true to take effect)
Options Description Nalakuvara's Predefined Value
cookies.enableDefaultPreferences Predefine Google Preferences false
cookies.enableInterfaceLanguage Specify Interface Language false
cookies.interfaceLanguage Interface Language (cookies.enableInterfaceLanguage has to be true to take effect) zh-TW
cookies.enableSearchLanguage Specify Search Language false
cookies.searchAnyOrSelected Search Any Language or Only Selected Languages (cookies.enableSearchLanguage has to be true to take effect) all
cookies.searchLanguage Specify Languages to Search (cookies.searchAnyOrSelected has to be selected to take effect) lang_zh-TW
cookies.enableSafeSearch Enable SafeSearch false
cookies.SafeSearch SafeSearch Option (cookies.enableSafeSearch has to be true to take effect)
  • 1: Strict - Filter Images and Language
  • "empty": Default - Filter Images Only
  • 4: None - Do Not Filter At All
4
cookies.enableResultsPerPage Specify Results Per Page false
cookies.ResultsPerPage Results Per Page (cookies.enableResultsPerPage has to be true to take effect) 10
cookies.enableResultsWindow Specify Results Window false
cookies.OpenSearchResultsInNewWindow Open Search Results in New Window (cookies.enableResultsWindow has to be true to take effect) false
Filter /* filtertab */
Options Description Nalakuvara's Predefined Value
misc.filterlist Filter Rules

Nalakuvara prompts users to change these values upon installation.

HanConvert is not a mature solution yet. It could not translate between Traditional Chinese and Simplified Chinese yet. It can, however, at least do characters level conversion between these two language. Next step will be improving it to phrase level conversion. Later, full translation maybe. HanConvert could be accessed via Toolbar buttons, which will be discussed later, in "Altering Menus and Toolbars" section. There is also another User JavaScript file to enable conversion automatically for all web pages; this is undesirable for it does too much compared with Opera's clean nature.

Opera follows W3C Web Standards but fails on W3C Ruby Annotation. HTML Ruby makes up this gap via JavaScript and CSS. It comes with a seperate ruby.settings.js to adjust its behavior:

HtmlRubySettings (OPTION: VALUE,)
Options Description Nalakuvara's Predefined Value
rubyTextSize The Size of Ruby Text (The size of Ruby Base is '1em') '.55em'
maxPageLength Maximum Page Length to Force Closing Tags (to prevent slowing down)
  • 0: Do Not Close Tags At All
  • -1: Always Close Tags
-1
spaceRubyText Space Ruby Text As Tight As Possible true
showNotice Show Notice via opera.postError false
processDynamicContent Process Dynamic Content false

Nalakuvara prompts users to change these values upon installation, too.

Open in Background with Long Press is for those who do not use mouse gesture. It works only on actual <a> links. Sadly some users reported that this User JavaScript might slow down web games on Facebook. Nalakuvara notes this issue before insltalling it.

Textarea Backup is a Greasemonkey User JavaScript. It needs Emulate GM functions to work in Opera. There is one variable in its textareabackup.js:

textareabackup.js (var OPTION = VALUE;)
Options Description Nalakuvara's Predefined Value
shelfLife The Duration That Backups Should Stored, in Seconds. 3600

Again, Nalakuvara prompts users to change these values upon installation.

Remember: if and only if any of User JavaScript above is installed, enable and tweak User JavaScript related preferences in operaprefs,ini.

Finally, there are Plug-Ins to connect Opera to other applications. Usually Plug-Ins are platform specified and thus will not be cross-platformed. There is only one Plug-In used in Nalakuvara, and only available on Windows: npviewinie, to render web pages using IE's trident engine without leaving Opera, just like Firefox extension "IE Tab" does.

The core of npviewinie is a npie_opera.dll, which should be in OPERA_INSTALL_PATH\program\plugins\ or anywhere listed in the opera:config#UserPrefs|PluginPath preference. Then we could embed an ie_opera object using an <embed> tag with type="application/ie_opera" attribution. This, too, could be performed via a Toolbar button, which will be discussed later, in "Altering Menus and Toolbars" section. There is also a seperate Autorender.in.IE.js to load listed web pages with ie_opera object automatically. This Autorender.in.IE.js, surely, should be in the User JavaScript path, with related perferences enabled to take effect.

npviewinie might not be usable in Windows Vista and Windows 7 due to Data Execution Prevention (DEP). The workaround is to turn DEP off with the following command invoked by Administrator:

bcdedit /set nx alwaysoff

Users have to reboot their system to take effect, too. With DEP disabled, other security issues might be raised. This infomation should be revealed to users, too.

Java Applets, on the other hand, provides a cross-platformed solution, which might be slower but work just fine. If users do not have JRE installed before, Opera might prompt to install JRE at the first run of any Java Applet. On some platforms users have to install JRE through system's package management system. On Ubuntu, for example, one has to intsall sun-java6-bin package via Synaptic Package Manager to make Java Applet work.

Nalakuvara uses ZTerm Applet to handle telnet:// and ssh:// protocols which are necessary for telnet-based BBS. There are two different ways to include this 3rd party component into Nalakuvara: install files locally, or use applet page hosted at http://ztermapplet.z6i.org/. Either way, ZTerm Applet stores its preferences in a .ztermrc file. This file is located at %USERPROFILE% on Windows, ~ on Linux/FreeBSD.

By default, ZTerm Applet uses IE as an external browser on Windows, and Firefox on Linux/FreeBSD. We could predefine it to Opera by editing .ztermrc:

external-browser-command::opera %u

On Linux, we could tweak ZTerm Applet more to make it look better:

external-browser-command::opera %u
font.antialias::true
font.family::AR PL UMing TW MBE
font.vertical-gap::1
locale.language::en
use-system-look-and-feel::true

On Ubuntu, again, there is 文泉驛等寬正黑 font for better look:

external-browser-command::opera %u
font.antialias::true
font.family::文泉驛等寬正黑
font.vertical-gap::1
locale.language::en
use-system-look-and-feel::true

And the applet page (local or remote) could be accessed via Bookmark, Bookmarklet, or Toolbar button. I prefer using Toolbar button and will talk about this later in "Altering Menus and Toolbars" section.

Altering Menus and Toolbars

With 3rd party components installed, there should be some ways to access them conveniently. Toolbar buttons is one of the best practical ways. New features (buttons) could be hidden by default, preserving Opera's default UI layout; users could also remove unwanted features, and revert them back easily.

Customized Toolbar buttons are stored in the [Customize Toolbar Custom.content] section of standard_toolbar.ini:

[Customize Toolbar Custom.content]
Button0, "Go to page"="Go to page, "javascript:void(function (){subscriptions = [];linksList = document.getElementsByTagName('link');for ( i = 0; i < linksList.length; i++ ){ type = linksList[i].type;if ( type == 'application/rss+xml' || type == 'application/atom+xml' || type == 'application/rdf+xml' ){ subscriptions.push( { 'title':linksList[i].title, 'href':linksList[i].href } );}}if ( subscriptions.length == 0 ) return;str = '你要訂閱哪個源料?請輸入編號\n';for ( i = 0; i < subscriptions.length; i++ ){str += i + ': ' + subscriptions[i].title + '\n';}str = str.substr( 0, str.length - 1 );ret = prompt( str );if ( ret < 0 || ret >= subscriptions.length ) return;document.location.href = 'feed://' + subscriptions[ret].href;})()", 1, "以支援 feed: 協定的桌面源料閱讀軟體來訂閱源料", "RSS""
Button1, "Select user CSS file"="Select user CSS file, 0, , "Flash Blocker 啟用中", "Transfer Loading" > Deselect user CSS file, 0, , "Flash Blocker 已停用", "Transfer Failure""
Button2, "Select user CSS file"="Select user CSS file, 1, , "Grafik Blocker 啟用中", "Transfer Loading" > Deselect user CSS file, 1, , "Grafik Blocker 已停用", "Transfer Failure""
Button3, "依據結構 (nth-child) 來阻擋網頁元素"="Go to page, "javascript:navigator.ujs_adblock.block()", , "依據結構 (nth-child) 來阻擋網頁元素", "Delete""
Button4, "阻擋網頁元素"="Go to page, "javascript:navigator.ujs_adblock.block(true)", , "阻擋網頁元素", "Delete""
Button5, "還原被擋掉的網頁元素"="Go to page, "javascript:navigator.ujs_adblock.unblock()", , "還原被擋掉的網頁元素", "Mail Redirected""
Button6, "還原前一個擋掉的網頁元素"="Go to page, "javascript:navigator.ujs_adblock.unblock(true)", , "還原前一個擋掉的網頁元素", "Mail Redirected""
Button7, "手動輸入要擋掉的 CSS 選擇符"="Go to page, "javascript:navigator.ujs_adblock.edit()", , "手動輸入要擋掉的 CSS 選擇符", "Window Mail Compose Icon""
Button8, "View in IE Tab"="Go to page, "javascript:(function(){var h=location.href;if(!h||/^(javascript|about|opera):/i.test(h)){return}window.open().document.write('<html>'+'<head>'+'<title>'+(document.title?document.title:location.href).replace(/</g,'&lt;')+' - view in ie</title>'+'<style type=\x22text/css\x22>body{margin:0;padding:0;}embed{width:100\x25;height:100\x25;}</style>'+'</head>'+'<body>'+'<script type=\x22text/javascript\x22'+'src=\x22data:text/javascript,'+encodeURIComponent('document.write(\'<embed type=\x22application/viewinie\x22 param-location=\x22'+location.href+'\x22></embed>\');')+'\x22>'+'</script>'+'</body>'+'</html>')})();", , "View in IE", "View""
Button9, "View in IE Same Tab"="Go to page, "javascript:(function(){var h=location.href;if(!h||/^(javascript|about|opera):/i.test(h)){return}document.write('<html>'+'<head>'+'<title>'+(document.title?document.title:location.href).replace(/</g,'&lt;')+' - view in ie</title>'+'<style type=\x22text/css\x22>body{margin:0;padding:0;}embed{width:100\x25;height:100\x25;}</style>'+'</head>'+'<body>'+'<script type=\x22text/javascript\x22'+'src=\x22data:text/javascript,'+encodeURIComponent('document.write(\'<embed type=\x22application/viewinie\x22 param-location=\x22'+location.href+'\x22></embed>\');')+'\x22>'+'</script>'+'</body>'+'</html>')})();", , "View in IE Same Tab", "View""
Button10, "繁"="Go to page, "javascript:void(TongWen.trans2Trad(document));", , "繁", "A""
Button11, "简"="Go to page, "javascript:void(TongWen.trans2Simp(document));", , "简", "A""
Button12, "BBS"="Go to page, "file://localhost/C:/ZTerm/ZTermApplet.html", , "BBS", "A""
Button13, "Google 即時小字典"="Go to page, "javascript:function translate(word){var glf=document.getElementById('glf');glf.contentWindow.gtrans(word)};function findAndReplace(searchText,replacement,searchNode){var regex=typeof searchText==='string'?new RegExp(searchText,'g'):searchText,childNodes=(searchNode||document.body).childNodes,cnLength=childNodes.length,excludes='html,head,style,title,link,meta,script,object,textarea,iframe';while(cnLength--){var currentNode=childNodes[cnLength];if(currentNode.nodeType===1&&(excludes+',').indexOf(currentNode.nodeName.toLowerCase()+',')===-1){arguments.callee(searchText,replacement,currentNode)}if(currentNode.nodeType!==3||!regex.test(currentNode.data)){continue}var parent=currentNode.parentNode,frag=(function(){var html=currentNode.data.replace(regex,replacement),wrap=document.createElement('div'),frag=document.createDocumentFragment();wrap.innerHTML=html;while(wrap.firstChild){frag.appendChild(wrap.firstChild)}return frag})();parent.insertBefore(frag,currentNode);parent.removeChild(currentNode)}};function inject(){findAndReplace('\\b[^ ]+\\b',function(term){return'<span onmouseover=\'translate(this)\'>'+term+'</span>'})};function init(){var glf=document.createElement('iframe');glf.id='glf';glf.width=0;glf.height=0;glf.frameborder=0;glf.style.borderWidth='0';glf.style.borderStyle='none';glf.style.position='fixed';glf.style.top='10px';glf.style.right='10px';document.body.appendChild(glf);var doc=glf.contentDocument;doc.open();doc.write('<head><title>Sample html</title><script type=\'text/javascript\' src=\'http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22language%22%2C%22version%22%3A%221%22%7D%5D%7D\'></script><script type=\'text/javascript\'>function gtrans(word) {if(word.title) return; word.title = \'translating...\'; var text = word.innerHTML; google.language.detect(text, function(result) { if (!result.error && result.language) { google.language.translate(text, result.language, \'zh-tw\', function(result) {if (result.translation) { word.title = text + \': \' + result.translation;}});}});};</script></head><body style=\'margin:0; background-color: transparent;\'><div id=\'branding\' style=\'width : 0px; height : 0px; text-align: left;\'></div></body>');doc.close();inject()};init();", 1, "Google 即時小字典", "Window Chat Room Icon""
Button14, "搜尋已選詞"="Hotclick search, , , "搜尋已選詞", "Search Web""
Button15, "站內搜尋"="Go to page, "javascript:var t=window.location.hostname;var s=prompt('Google site search - enter search string:','');if(s){if(s.match(/^d%5cs.+/)){s=s.substring(2,s.length);t=t.match(/%5b^%5c.%5d+%5c.%5cw{2,4}$/)+''};void(location.href='http://www.google.com/search?q=site:'+t+'+'+s+'&sourceid=opera')}", 1, "站內搜尋", "Search Web""

All customized buttons here will show up in the "My buttons." The main problem here is that users might install different 3rd party components and one standard_toolbar.ini could not fit them all. During installation/patch process, Nalakuvara copies one of sixteen predefined standard_toolbar.ini to OPERA_INSTALL_PATH\ui\ according to users' selection.

The modified standard_toolbar.ini is renamed to "Opera Nalakuvara Standard" to distinguish with the original one. What if it just does not show up? No problem, users could still install Nalakuvara's customized buttons from user documents, which will be discussed later, in "User Documents" section.

Menus are a little tricky. By Nalakuvara's guidelines, there should be as less change as possible in menus. The only "have-to" is Opera's built-in dictionary function.

By default, "Opera Standard" menu contains one Hotclick (right-click) search entry for Merriam-Webster Online Dictionary, one for English Wikipedia, and one set of translation function using Yahoo! BabelFish which includes:

  • English to French
  • English to German
  • English to Italian
  • English to Portuguese
  • English to Spanish
  • French to English
  • French to German
  • French to Italian
  • French to Portuguese
  • French to Spanish
  • German to English
  • German to French
  • Italian to English
  • Italian to French
  • Portuguese to English
  • Spanish to English
  • Spanish to French
  • English to Japanese
  • Japanese to English

These are quite useful for American/European users. For Taiwanese users, however, they do not help much. There are some local popular web dictionary services in Taiwan, and Yahoo! BabelFish supports Traditional Chinese to/from English too. It is better to include these feature into Hotclick searches.

The goal here is to expand "Dictionary" and "Encyclopedia" entries to submenus (original Merriam-Webster Online Dictionary and English Wikipedia), and tweak "Translate" submenu to fit the need of Taiwanese users:

  • Dictionary
    • Yahoo! Taiwan Dictionary
    • Merriam-Webster Online Dictionary
    • Taiwan National Language Composite Search
  • Encyclopedia
    • Chinese Wikipedia
    • English Wikipedia
    • Japanese Wikipedia
    • Uncyclopedia
  • Translate
    • English to Traditional Chinese
    • Traditional Chinese to English
    • Japanese to English
    • French to English
    • German to English
    • Italian to English
    • Portuguese to English
    • Spanish to English
    • English to Japanese
    • English to French
    • English to German
    • English to Italian
    • English to Portuguese
    • English to Spanish

This modification is through three files:

  • LANGUAGE_CODE.lng which changes menu text according to specific UI language;
  • search.ini which defines actual Hotclick searches;
  • standard_menu.ini which defines actual Hotclick menu.

The default searches are predefined in the search.ini. Just like bookmarks.adr of default bookmarks, search.ini could be locale-based. This makes more sense for we could tweak above menu just for Taiwanese users, i.e., those who use Traditional Chinese UI language.

Let us start with Hotclick translate submenu. The [Translate menu] section of OPERA_INSTALL_PATH\ui\standard_menu.ini is as below:

[Translate menu]
Item, MI_IDM_SELTRANSLATE_FR_DE	= Hotclick search, 107
Item, MI_IDM_SELTRANSLATE_FR_IT	= Hotclick search, 108
--------------------1
Item, MI_IDM_SELTRANSLATE_JA_EN	= Hotclick search, 119
Item, MI_IDM_SELTRANSLATE_FR_EN	= Hotclick search, 106
Item, MI_IDM_SELTRANSLATE_DE_EN	= Hotclick search, 111
Item, MI_IDM_SELTRANSLATE_IT_EN	= Hotclick search, 113
Item, MI_IDM_SELTRANSLATE_PT_EN	= Hotclick search, 115
Item, MI_IDM_SELTRANSLATE_ES_EN	= Hotclick search, 116
--------------------2
Item, MI_IDM_SELTRANSLATE_EN_JA	= Hotclick search, 118
Item, MI_IDM_SELTRANSLATE_EN_FR	= Hotclick search, 100
Item, MI_IDM_SELTRANSLATE_EN_DE	= Hotclick search, 101
Item, MI_IDM_SELTRANSLATE_EN_IT	= Hotclick search, 102
Item, MI_IDM_SELTRANSLATE_EN_PT	= Hotclick search, 103
Item, MI_IDM_SELTRANSLATE_EN_ES	= Hotclick search, 104

Then modify OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng to match this change:

1208490414="英文 > 法文(F)"
1208490335="英文 > 德文(G)"
1208490515="英文 > 義大利文(I)"
1208490746="英文 > 葡萄牙文(P)"
1208490382="英文 > 西班牙文(S)"
1209820046="法文 > 英文(2)"
1209820004="英文 > 繁體中文(T)"
1209820184="繁體中文 > 英文(E)"
1206981023="德文 > 英文(3)"
1213449683="義大利文 > 英文(4)"
1221751130="葡萄牙文 > 英文(5)"
1208670062="西班牙文 > 英文(6)"
1208490529="英文 > 日文(J)"
1213952801="日文 > 英文(1)"

And OPERA_INSTALL_PATH\locale\zh-tw\search.ini to change the actual Hotclick search:

[Search Engine 7]
UNIQUEID=96D0060E5FC311DDBEA89A1656D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=fr
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=100
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 8]
UNIQUEID=C1629A765FC311DDB2CB3F1956D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=de
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=101
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 9]
UNIQUEID=EED3C7145FC311DD82E4CE1A56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=it
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=102
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 10]
UNIQUEID=14E03A145FC411DD97AE5E1C56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=pt
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=103
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 11]
UNIQUEID=090D0C025FC511DD88CAAB2856D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=es
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Verbtext=017063
Search Type=104
Position=-1
Nameid=291960

[Search Engine 12]
UNIQUEID=37F636385FC511DDA9FAC42A56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=fr&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=106
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 13]
UNIQUEID=6E70644A5FC511DD89AD0F2D56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=zt
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=107
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 14]
UNIQUEID=95C831945FC511DD952DE52E56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=zt&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=AUTODETECT-ZH
Search Type=108
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 17]
UNIQUEID=DF49D89E5FC611DD9581F43E56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=de&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=111
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 19]
UNIQUEID=88383F7C5FC711DDBC78BD4756D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=it&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=113
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 21]
UNIQUEID=FF719C3C5FC711DD986F284E56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=pt&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=115
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 22]
UNIQUEID=BD0EEE0A5FCA11DDAE6D867456D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=es&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=116
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 24]
UNIQUEID=0B7FB2A45FCB11DD8980147856D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=en&to=ja
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=118
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 25]
UNIQUEID=4031DD385FCB11DDAE6A3E7B56D89593
Name=
URL=http://redir.opera.com/translation/?text=%s&from=ja&to=en
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=EUC-JP
Search Type=119
Verbtext=0
Position=-1
Nameid=291960

The "Translate" submenu works now. Now let us expand "Dictionary" and "Encyclopedia" entries to submenus by modifying [Hotclick Popup Menu] section of the OPERA_INSTALL_PATH\ui\standard_menu.ini:

[Hotclick Popup Menu]
Item, MI_IDM_DOCCOPY			= Copy
Item, M_COPY_TO_NOTE			= Copy to note
Platform Win2000-Unix-Mac-QNX, Feature Voice, Item, M_HOTCLICK_MENU_ITEM_SPEAK = Speak selection
--------------------1
Item, MI_IDM_SELSEARCH				= Hotclick search, 200
Submenu, MI_IDM_SEARCH_DUMMY_PARENT, Internal Search With
Submenu, 999999999, Dictionary menu
Submenu, 999999998, Encyclopedia menu
--------------------2
Submenu, MI_IDM_SELTRANSLATE_EN_FR_PARENT, Translate menu
--------------------3
Item, M_HOTCLICK_POPUP_MENU_GOTO_URL				= Go to page, "%t"
Item, MI_IDM_SELMAIL			= Send text in mail

The Submenu command creates a submenu. Since the language string numbering schema remains unknown to the public, the locale-specific submenu names are using 999999999 and 999999998 as language string numeric identifier. We have to add these two strings in OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng too:

999999999="查字典(D)"
999999998="查百科(P)"

Do not forget to define actual "Dictionary" and "Encyclopedia" submenus in OPERA_INSTALL_PATH\ui\standard_menu.ini:

[Dictionary menu]
Item, MI_IDM_SELTRANSLATE_FR_PT			= Hotclick search, 109
Item, MI_IDM_SELDICTIONARY			= Hotclick search, 50
--------------------1
Item, MI_IDM_SELTRANSLATE_DE_FR			= Hotclick search, 112

[Encyclopedia menu]
Item, MI_IDM_SELTRANSLATE_FR_ES			= Hotclick search, 110
Item, MI_IDM_SELENCYCLOPED			= Hotclick search, 51
Item, MI_IDM_SELTRANSLATE_IT_FR			= Hotclick search, 114
--------------------1
Item, MI_IDM_SELTRANSLATE_ES_FR			= Hotclick search, 117

Again, the locale-specific names in the OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng:

-1539396211="韋氏英英字典(W)"
1634087069="英文維基百科(E)"
1209820415="Yahoo!奇摩字典"
1209820051="中文維基百科(Z)"
1206981060="國家語文綜合連結檢索"
1213449720="日文維基百科(J)"
1208670099="偽基百科(U)"

And the actual Hotkey searches in the OPERA_INSTALL_PATH\locale\zh-tw\search.ini:

[Search Engine 5]
UNIQUEID=CD139D765FC211DDA345390D56D89593
Name=
URL=http://en.wikipedia.org/wiki/Special:Search?search=%s
ICON=http://redir.opera.com/favicons/wikipedia/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=51
Verbtext=0
Position=-1
Nameid=65188

[Search Engine 6]
UNIQUEID=9923D42C5FC211DDA01C470B56D89593
Name=
URL=http://www.merriam-webster.com/dictionary/%s
ICON=http://www.merriam-webster.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=50
Verbtext=0
Position=-1
Nameid=65187

[Search Engine 15]
UNIQUEID=C482AAFA5FC511DD9EE1413256D89593
Name=
URL=http://tw.dictionary.yahoo.com/search?ei=UTF-8&p=%s
ICON=http://babelfish.yahoo.com/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=109
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 16]
UNIQUEID=EBB05C8A5FC511DD829BD83356D89593
Name=
URL=http://zh.wikipedia.org/w/index.php?title=Special%3A%E6%90%9C%E7%B4%A2&redirs=0&search=%s&fulltext=Search&ns0=1
ICON=http://redir.opera.com/favicons/wikipedia/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=110
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 18]
UNIQUEID=515B56A65FC711DD99D77C4556D89593
Name=
URL=http://www.nlcsearch.moe.gov.tw/EDMS/admin/dict3/search_go.php
Query=dictlist=47﷐2C46﷐2C51﷐2C18﷐2C16﷐2C13﷐2C20﷐2C19﷐2C53﷐2C12﷐2C14﷐2C17﷐2C48﷐2C57﷐2C24﷐2C25﷐2C26﷐2C29﷐2C30﷐2C31﷐2C32﷐2C33﷐2C34﷐2C35﷐2C36﷐2C37﷐2C39﷐2C38﷐2C41﷐2C42﷐2C43﷐2C45﷐2C50﷐2C&qstr=%s&chkSubject=on&hdnSubject=A&dict=&hdnCheckAll=checked&dict0=&dict0=47&dict0=46&dict0=51&dict1=&dict1=18&dict1=16&dict1=13&dict1=20&dict1=19&dict1=53&dict1=12&dict1=14&dict1=17&dict1=48&dict2=&dict2=57&dict2=24&dict3=&dict3=25&dict3=26&dict3=29&dict3=30&dict3=31&dict4=&dict4=32&dict4=33&dict4=34&dict4=35&dict4=36&dict4=37&dict4=39&dict4=38&dict4=41&dict5=&dict5=42&dict5=43&dict5=45&dict5=50&pageno=
Key=
Is post=1
Has endseparator=0
Encoding=big5
Search Type=112
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 20]
UNIQUEID=B2227D485FC711DD9F8DA84956D89593
Name=
URL=http://ja.wikipedia.org/wiki/特別:検索?search=%s&go=%E8%A8%98%E4%BA%8B%E8%A1%A8%E7%A4%BA
ICON=http://redir.opera.com/favicons/wikipedia/favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=114
Verbtext=0
Position=-1
Nameid=291960

[Search Engine 23]
UNIQUEID=E71079445FCA11DDBA1D577656D89593
Name=
URL=http://zh.uncyclopedia.info/index.php?title=%E7%89%B9%E6%AE%8A%3A%E6%90%9C%E5%B0%8B&search=%s&go=%E9%80%B2%E5%85%A5
ICON=http://images.uncyc.org/zh-tw/6/64/Favicon.ico
Query=
Key=
Is post=0
Has endseparator=0
Encoding=utf-8
Search Type=117
Verbtext=0
Position=-1
Nameid=291960

Any search which Search Type is not 0 will not be shown in Search Bar, but could be invoked by "Hotclick search" command. The reason to use "Hotclick search" rather than "Go to page" is to specify input encoding (Encoding=foo) and/or specify GET/POST submission (Is post=0_OR_1).

Since Hotclick menu could be locale-based, we could do further for English, Simplified Chinese, or any other UI languages. In sum, this following table describes language files changing:

OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng
OPERA_INSTALL_PATH\locale\zh-cn\zh-cn.lng
OPERA_INSTALL_PATH\locale\en\en.lng
String Numeric Identifier Opera's Original Nalakuvara Modification
-1539396211 字典(D) 韋氏英英字典(W)
字典 iCIBA爱词霸
Dictionary Merriam-Webster Online Dictionary
1634087069 百科全書(E) 英文維基百科(E)
百科全书 英语维基百科(E)
Encyclopedia English Wikipedia
1209820046 法文 > 英文(E) 法文 > 英文(2)
法语译英语 法语译英语(2)
French to English (2) French to English
1209820004 法文 > 德文(M) 英文 > 繁體中文(T)
法语译德语 英语译中文(C)
French to German (T) English to Traditional Chinese
1209820184 法文 > 義大利文(T) 繁體中文 > 英文(E)
法语译意大利语 中文译英语(E)
French to Italian (E) Traditional Chinese to English
1209820415 法文 > 葡萄牙文(O) Yahoo!奇摩字典
法语译葡萄牙语 台湾Yahoo!奇摩字典
French to Portuguese Yahoo! Taiwan Dictionary
1209820051 法文 > 西班牙文(A) 中文維基百科(Z)
法语译西班牙语 中文维基百科(Z)
French to Spanish Chinese Wikipedia
1206981023 德文 > 英文(N) 德文 > 英文(3)
德语译英语 德语译英语(3)
German to English (3) German to English
1206981060 德文 > 法文(R) 國家語文綜合連結檢索
德语译法语 台湾国家语文综合连结检索
German to French National Language Composite Search
1213449683 義大利文 > 英文(L) 義大利文 > 英文(4)
意大利语译英语 意大利语译英语(4)
Italian to English (4) Italian to English
1213449720 義大利文 > 法文(Y) 日文維基百科(J)
意大利语译法语 日语维基百科(J)
Italian to French Japanese Wikipedia
1221751130 葡萄牙文 > 英文(U) 葡萄牙文 > 英文(5)
葡萄牙语译英语 葡萄牙语译英语(5)
Portuguese to English (5) Portuguese to English
1208670062 西班牙文 > 英文(H) 西班牙文 > 英文(6)
西班牙语译英语 西班牙语译英语(6)
Spanish to English (6) Spanish to English
1208670099 西班牙文 > 法文(B) 偽基百科(U)
西班牙语译法语 伪基百科(U)
Spanish to French Uncyclopedia
1208490529 英文 > 繁體中文(C) 英文 > 日文(J)
英语译日语 英语译日语(J)
English to Japanese (J) English to Japanese
1213952801 繁體中文 > 英文(V) 日文 > 英文(1)
日语译英语 日语译英语(1)
Japanese to English (1) Japanese to English
999999999 查字典(D)
查字典(D)
Dictionary
999999998 查百科(E)
查百科(E)
Encyclopedia

The reason to do this is that some Taiwanese users might use computer in other countries, such as America and China, and not always be able to use Opera with Traditional Chinese UI. With English and Simplified Chinese UI predefined, these users could also use tweaked menu, too.

The English (en) and the Simplified Chinese (zh-cn) versions of search.ini are different with the Traditional Chinese (zh-tw) one. Most locale-specific searches are preserved during Nalakuvara's editing process.

This is not over yet. Encoding is always a big problem in CJK, so Taiwanese users often switch web page encoding. Many users asked if encoding submenu could be included in the right click menu. Here you are:

[Document Popup Menu]

Item, MI_IDM_Prev_PM,				= Back
Item, MI_IDM_Next_PM,				= Forward
Item, M_REWIND,				= Rewind
Item, M_FAST_FORWARD,				= Fast Forward
--------------------1
Item, MI_IDM_Reload_PM,				= Reload
Submenu, MI_IDM_AUTORELOAD_TOGGLE_PARENT, Reload Menu
--------------------2
Item, M_DOCUMENT_POPUP_MENU_BOOKMARK_PAGE		= Add to bookmarks, 1
Item, MI_IDM_POPUP_ADDRESS			= Copy document address
Item, MI_IDM_SEND_URL_EMAIL		= Send document address in mail
--------------------3
Item, MI_IDM_Print				= Print document
Item, MI_IDM_Kilde				= View document source
Item, M_DOCUMENT_POPUP_MENU_VALIDATE			= Validate frame source
Submenu, M_OPEN_WITH, Open in menu
--------------------5
Include, Internal Frame
Include, Internal Document Background
--------------------7
Submenu, MI_IDM_ENCODING_AUTOMATIC_PARENT, Encoding Menu
Item, M_BLOCK_CONTENT = Content block mode on | Content block mode off
Item, M_EDIT_SITE_PREFERENCES = Edit site preferences
--------------------8
Item, MI_IDM_FULLSCREENTOGGLE			= Enter fullscreen | Leave fullscreen

Another requested feature is the ability to merge notes. It is quite simple:

[Note Item Popup Menu]
Item, MI_IDM_SELMAIL       = Send text in mail
--------------------1
Item, MI_IDM_HLITEM_CUT                            = Cut
Item, MI_IDM_HLITEM_COPY                            = Copy
Item, MI_IDM_HLITEM_PASTE                            = Paste
Item, 999999997                            = Copy & Paste to note
Item, 999999996                            = Copy & Delete & Paste to note
Item, MI_IDM_HLITEM_DELETE                            = Delete
--------------------5
Item, MI_IDM_HLITEM_SELECTALL                     = Select all
--------------------6
Item, M_BOOKM_PANEL_VIEW_MENU_SORT_BY_MY_ORDER       = Sort by column, -1
Item, M_BOOKM_PANEL_VIEW_MENU_SORT_BY_NAME       = Sort by column, 0
--------------------7
Item, M_NEW_NOTE       = New note
Item, SI_NEW_FOLDER_BUTTON_TEXT       = New folder
Item, M_NEW_SEPARATOR        = New Seperator

Right, here is introduced another two customized language string numeric identifiers, 999999997 and 999999996. Again we have to add these two strings to OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng:

; item for Nalakuvara
999999997="合併且保留"
999999996="合併"

And to multiple languages:

OPERA_INSTALL_PATH\locale\zh-tw\zh-tw.lng
OPERA_INSTALL_PATH\locale\zh-cn\zh-cn.lng
OPERA_INSTALL_PATH\locale\en\en.lng
String Numeric Identifier Opera's Original Nalakuvara Modification
999999997 合併且保留
合并且保留
Merge and Keep
999999996 合併
合并
Merge

Packing

Nalakuvara is almost done. We now have to pack bits and bytes into one.

On Windows, I first compile AutoHotKey scripts into .exe executive, then pack all necessary files into RAR SFX archive. RAR SFX archive could launch specific file upon file extraction. You could use NSIS too. RAR SFX is much easier to extract by standalone application, but sadly could not handle multiple languages well.

On Linux/FreeBSD, packing is quite simple. Just make tarballs. I specially use different tarball formats for different platforms: tar.bz2 for Ubuntu (deb) and FreeBSD, tar.gz for Fedora (rpm), tgz for generic Linux. This somehow helps users to distinguish their downloads.

To help users make sure that their downloads are intact, the file download page also provides MD5 checksum of each files. MD5, however, is a little too geeky. In order to help average users, there is a standalone file checker based on MD5 checksum and compiled from AutoHotKey script too. It is the one checker to check them all. If the downloaded file belongs to any one of the current releases, it reports file's detail, otherwise it asks users to download again. By providing this checker, novice users and advanced users could both make sure that their download file is correct with no trouble.

Documentation

Documentation is the basis for communication. I spend more time on documentation then coding/scripting. The importance of documentation is very clear; otherwise this article would not appear.

Documentation is just like making Nalakuvara: you have to fit the needs of geek and average users. User documents help users to understand the whole project, know where to tweak options back if needed, or how to apply changes manually. Geek documents are for geeks, for those who want to know actual process behind Nalakuvara, and for those who want to do a similar project.

Because Nalakuvara is for Taiwanese users, currently all documents are only in Traditional Chinese. This article you are reading now is the first English document of Nalakuvara.

User Documents

Nalakuvara documents often update, so they are only available on web so far. Main index of Nalakuvara describes the history of this project, TODOs, and knwon issues. Feature page introduces guidelines of Nalakuvara, details all features with screenshots, and links to add customized buttons. Download page lists all available downloads of current Nalakuvara version, with some supplied files such as script to enable mouse gesture trail. Change Log page records all changes since the first release of Nalakuvara. Users who use Patch Package will be led to the patched result page, which provides information in regard to several Nalakuvara's tweaked defaults, such as bookmarks and Toolbar buttons. In case Nalakuvara's patch does not work, users still know how to fix them by theirselves.

All these documents are user-oriented. This means that all information is in plain language, with images, lists, and tables to facilitate understanding. With these documents on hand, most users could easily find what they need, and I could easily answer most user questions by providing a single URL.

Geek Documents

Geek documents provide something extra for geek. Technical details page is just like a shorter version of this article, which explains many things, including how and why I made certain decisions, and how I implement all of those.

For hardcore geek, however, the actual documents are within scripts source. That is right, all scripts are commented nicely, line-by-line, in Traditional Chinese. There are even more details in those comments than in this article. (Would anyone like to see thousands lines of code in this article? I doubt that.) Studying these scripts, one could not only learn how to modify Opera, but also learn some AutoHotKey basis.

Geek documents help geeks to truly take control of Nalakuvara. I myself is one of its biggest beneficiary. Weeks have passed, I could still tell which line of the codes is doing what at a glance.

Test and Release

Packages could not be released even when files are well packed and documents are fully updated. It must be tested first. Also how should I release these packages is a question to consider first. In the following passage I will talk about these: test and release.

Test Environment

The first step of test is to prepare test environments. As mentioned before, virtual machine helps a lot. For any one of the platforms (OSes), it is better to take several snapshots to test with:

  • Brand new default intsallation;
  • Brand new default installation with all service packs from venders;
  • Brand new customized installation;
  • Brand new customized installation with all service packs from venders;
  • Brand new customized installation with all service packs from venders, and Opera 9.64 is installed with default options;
  • Brand new customized installation with all service packs from venders, and Opera 9.64 is installed with customized options;
  • Brand new customized installation with all service packs from venders, and Opera 10.00 is installed with default options;
  • Brand new customized installation with all service packs from venders, and Opera 10.00 is installed with customized options;
  • Brand new customized installation with all service packs from venders, with 3rd party web browser as system's default web browser;
  • Upgrade installation from previous versions.

You could add more situations in the list above. However, once you could make sure there will not be difference in certain situations, you should eliminate them to prevent from wasting time.

Route

A "route" is how users complete one process. Take Full Installation Package as an example, there are 249 possible routes. Nightmare begins with 10 test situations times 10 different systems, which makes 24,900 routes to test in total. It is quite impossible to fulfil them all. But at least you should perform all 249 routes in one situation, one system. Once or twice I was too lazy to do all the test, and some packages just fail stupidly.

Tips: save your own time by doing unit test. 249 routes could be two units with only 20 routes in total. You could also use debug code to help you:

; debug mode switch
DEBUGMODE = 1

; blah blah blah...
;
; some code here
;
; yada yada yada...

; print debug message only when debug mode is on
if ( DEBUGMODE = "1" ) {
MsgBox, 64, DEBUG MESSAGE, variable foo = %foo%
}

; blah blah blah...
;
; code continues
;
; yada yada yada...

Deploy

Test goes well. It is time to make project release public. Since I am using Perforce as version control system, that is the same way I pull updates to my web server. I set up a crontab:

P4PORT=HOST:PORT
P4USER=USERNAME

45 * * * * /usr/local/bin/p4 sync

This keeps files up-to-date hourly. It is enough for minor changes or routine maintenance. When I am ready to release a new build, just manually do p4 sync. Please note that by default p4 login gets a ticket that only validates for 43,200 seconds (i.e., 12 hours). In order to keep crontab working, you have to first specify Timeout: unlimited with p4 group command to create a group of users issued tickets that never expire.

My web server, on the other hand, has another problem. I host my web server with a 10M/2M ADSL connection, thus it could not serve more than 2Mbps outgoing bandwidth in total. There are still a few ways to balance traffic:

Coral Content Distribution Network (CoralCDN) provides a free peer-to-peer content distribution network. Just append .nyud.net to the hostname part of file downloading URLs:

<a href="http://Jedi.org.nyud.net/p4/Opera/pub/Release/Opera-10.00.Nalakuvara-RC2.exe">download</a>

I also use file hosting services such as RapidShare and other mirror sites to provide alternative downloads. Do not forget to provide file checksums (MD5/SHA1/SHA256 or so) to verify files.

Community

Community is the core value of any software projects. It is important to feed information to community, and get feedback from it.

Feed

When your project is exposed to public, thousands of visitors come. Most visitors come to visit only once; only very few will be back again. It means that most people will not pay much attention to any project.

If you want people to keep knowing your project progress, you have to do something. Feed, for example, is good to do this trick. People might subscribe your feeds during their one-time visit, and might come back again if you publish something interesting via feeds. There are also many other communication channels, such as Twitter or Plurk, which basically do the same job.

The point here is to create a "laziness-friendly" environment, so that people would like to involve at the first time.

Once the channel is set, talk often. Every time you find a bug, fix a bug, add a feature, write a document, or so, let people who scribed/followed to know. Feed your users and they will gather and grow up. That is the beginning of the community.

Feedback

The community, however, could not only rely on one-way communication. You have to listen to and talk to members. Some channels, such as Twitter and Plurk, are capable to joint conversation. You should use social platform where users used to be, too. Remember those place when doing background analysis? I spend lots of time on related forum like Ptt BBS every day. How users use your work might quite differ from your knowledge. The need of users evolves from time to time, so your project should evolve too. Of course, you still have to keep the guidelines in mind.

The fake User Agent string list mentioned in the end of "Tweak Defaults" section is one of the results of community contribution. About a month ago, I started a spreadsheet on Google Docs and Spreadsheets. The privilege of that spreadsheet is set to public, and every one is welcome to edit freely. Later I post this spreadsheet URL at Ptt BBS, and users start to contribute their finding.

It is neither easy nor simple to manage a community. Nalakuvara has a long way to go, and I still have a lot to learn. In the mean while, I want to recommand a new book, "The Art of Community," which is written by Jono Bacon, the Ubuntu Community Manager, and is published by O'Reilly. The best part of it is that this book is also released online under a Creative Commons Attribution-NonCommercial-ShareAlike license. Why not get a free PDF download right now?

Conclusion

There are many different ways to do things. You could do it quick-and-dirty, or make it step-by-step. From a long-term point of view, I believe that a solid path make things much easier. Even readers out of browser world still benefit from these details. That is why I take time to write documents and articles like this one.

Opera itself evolves, too. One day Opera might reach perfection and cover all features from Nalakuvara. At that time, there will be no need to continue Nalakuvara project. However, with all these documents, all contribution and community interaction will not be in vain.

Note: This article is published at Opera Developer Community, edited and splitted into 4 parts: Part 1, Part 2, Part 3, and Part 4.

Author: Jedi