Thursday, July 30, 2009

How to interpret a Linux core dump file

http://www.dialogic.com/support/helpweb/dxall/tn957.aspx

Symptom:
This technote provides information on how to interpret a Linux core dump file when an application running on the system, terminates unexpectedly, due to a segmentation fault and generates a core file.

Reason for the problem:
A segmentation fault generally occurs when a program attempts to access a memory location that it is not allowed to, or attempts to access a memory location in a way that is not allowed. The operating system will then kill the program and create a core file that programmers can use to figure out what went wrong. It contains detailed information about the nature of the crash, such as what caused the crash and what the program was doing when it happened.

Fix / Solution: 
A core dump can be caused by any number of issues that may or may not be related to a Dialogic® problem. This technical note describes how to gather information to determine if a Dialogic® API call may be the cause of a segmentation fault. Here are the basic steps to take in determining the cause for the core dump:

  1. To determine what program a core file came from, use the file command:
    <prompt> file core.1234
    core.1234: ELF 32-bit LSB core file of “app” (signal 11), Intel 80386, version 1, from “app”

    Note: The above output shows that program “app” is the executable which generated the core dump file.

  2. Then run GDB (The GNU Debugger) to view the contents of the core file with the following command line options:
    <prompt> gdb app core.1234 (where “app” is the application executable and “core.1234” is the core dump file)

  3. Once GDB has loaded up, you can run the “bt” command to display backtrace of the program stack.
    Example:
    (gdb) bt
    #0 0x40c8b6ec in s7_listen () from /usr/lib/libgcs7.so
    #1 0x40c8be4e in DlgcHost_GcSS7::s7_Listen () from /usr/lib/libgcs7.so
    #2 0x40278255 in gc_Listen () at eval.c:41
    #3 0x08049ac1 in route () at eval.c:41
    #4 0x0804986a in main () at eval.c:41
    #5 0x402c9507 in __libc_start_main (main=0x8049220 <main>, argc=2, ubp_av=0xbfffeae4, init=0x8048d64 <_init>, fini=0x804b4f0 <_fini>, rtld_fini=0x4000dc14 <_dl_fini>, stack_end=0xbfffeadc) at ../sysdeps/generic/libc-start.c:129


  4. Looking at the stack itself, it goes upward where the last executed function will always be frame 0. That is where the application experienced the segmentation fault:
    #0 0x40c8b6ec in s7_listen () from /usr/lib/libgcs7.so
    It lists the function ‘s7_listen’ and the library ‘libgcs7.so’ from which the segmentation fault (core dump) occurred.
    Note the last frame 0 doesn’t always tell the whole story so it’s a good idea to check a couple of frames below that to see if there are any recognizable functions. Sometimes the functions are from an internal library linked to the application, therefore look for the last external function call to see where the problem started at. In this case the application called the gc_Listen API call within the route subroutine as per:
    #2 0x40278255 in gc_Listen () at eval.c:41
    #3 0x08049ac1 in route () at eval.c:41

Additional information:
Here are some further tips on narrowing down the cause of a segmentation fault (core dump):

  1. Recompile the program with the –g option and re-run the test again. This will enable extra debug information which only GDB can use when reading the stack in the core file. This option is available for both gcc and g++ compilers. <prompt> gcc app.c –g –o app –l(libs to be linked with you application)
    As a result the core dump file will now generate the following backtrace:
    (gdb) bt
    #0 0x40c8b6ec in s7_listen () from /usr/lib/libgcs7.so
    #1 0x40c8be4e in DlgcHost_GcSS7::s7_Listen () from /usr/lib/libgcs7.so
    #2 0x40278255 in gc_Listen () at eval.c:41
    #3 0x08049abd in route (i=1, tsinfo=0x804f1b0) at app.c:274
    #4 0x0804986a in main (argc=2, argv=0xbfffeee4) at app.c:190
    #5 0x402c9507 in __libc_start_main (main=0x8049220 <main>, argc=2, ubp_av=0xbfffeee4, init=0x8048d64 <_init>, fini=0x804b4f0 <_fini>, rtld_fini=0x4000dc14 <_dl_fini>, stack_end=0xbfffeedc) at ../sysdeps/generic/libc-start.c:129


    Note: The output now shows additional information such as parameters passed within the function calls and line numbers specific to the source file (.c) where the function was called from.

    Example: Frame 3 shows that the route function received two parameters, an integer and a pointer to a memory address where it was called from line #274 of app.c file.

  2. In order to step thru the frames of the stack and view additional information use the “up” and “down” commands:
    Example of moving up the stack to frame #4 (after executing “up” 4 times):
    (gdb) up
    #3 0x08049abd in route (i=1, tsinfo=0x804f1b0) at app.c:274
    274 if (gc_Listen(port[i].ldev,tsinfo,EV_SYNC) != GC_SUCCESS ) {


    Note: Each example shows the contents of that line in the app.c file.

  3. At any point use the “print” command to show contents of a memory address passed as a pointer to the function:

    Example of printing the contents of pointer tsinfo:
    (gdb) print *tsinfo
    $1 = {sc_numts = 1, sc_tsarrayp = 0x0}


    Notice the values of the two members of the structure passed to the route function call.

Tuesday, July 28, 2009

江苏省建设厅前厅长徐其耀在给儿子的信中



要有文凭,但不要真有知识,真有知识会害了你。有了知识你就会独立思考,而独立思考是从政的大忌。别看现在的领导都是硕士博士,那都是假的。



Sunday, July 19, 2009

Overview of Fundamental Real-Time Concepts and Terms

http://www.real-time.org/realtimeoverview.htm


This is a 1-page synopsis of my formulation of the most fundamental yet almost universally misunderstood concepts and terms of real-time computing. This formulation is elaborated on the pages listed in the right hand Outline column. This formulation has been demonstrated to greatly facilitate the cost-effective construction of real-time computing systems that are far more complex (e.g., dynamic, adaptive, distributed) than can be constructed using traditional ill-defined real-time concepts.

Real-time computing is about satisfying time constraints acceptably well with acceptable predictability according to application- and situation-specific acceptability criteria, given the current circumstances.

Thus, there are two fundamental factors involved in what "real-time," "hard real-time," and "soft real-time" mean:

bullettime constraints on individual activities;
bulletcriteria for using those time constraints to achieve system timeliness that is acceptably optimal with acceptable predictability.

Very often when people discuss what "real-time," "hard real-time," and "soft real-time" mean, they focus on the first factor and largely overlook the second this results in serious misunderstandings.

Time Constraints

Most systems (not just those that are commonly considered "real-time" ones) include activities that have time constraints i.e., activities that each have utility to the system as a function of when that activity completes. Such activities could be the conspicuous cornerstone of a time-critical targeting application [insert your own example here]), or they could be buried inconspicuously inside device drivers for a desktop PC operating system.

The most familiar example of a time constraint is a deadline, which is (properly but not popularly) defined as a time until which the activity's completion has more utility to the system, and after which the activity's completion has less utility.

A hard deadline is the special case where utility is the binary set {1,0}: completing the activity by the deadline results in the system receiving all the utility possible from that activity, and completing the activity after the deadline results in zero utility (i.e., resources consumed by the activity were wasted, such as when a message is transmitted from a satellite after it has dropped below the horizon [insert your own example here]) or some negative value of utility (i.e., the activity was counter-productive, such as when an incoming missile is intercepted by an anti-missile missile from its target when it is only 20 meters away [insert your own example here]).

The general case of a deadline (which is a soft deadline) has utility measured in terms of lateness (completion time minus deadline), tardiness (positive lateness), or earliness (negative lateness). Larger positive values of lateness or tardiness represent lower utility, and consequently larger positive values of earliness represent greater utility.

The significance of more or less utility in both the hard deadline and soft deadline cases is a system- or application- or situation-specific decision, and (contrary to popular mis-usage) is not part of the proper definitions of hard and soft deadlines. Missing a hard deadline may be either relatively insignificant (e.g., a sensor data sample is missed [insert your favorite example here]) or relatively significant (e.g., a torpedo alert is missed [insert your own example here]). Any given value of tardiness may be either relatively insignificant (e.g., affecting the battery power needed to transmit from a satellite as it declines toward the horizon [insert your own example here]) or relatively significant (e.g., affecting the circular error probability of kill [insert your own example here]).

Deadlines are not intrinsically short; they may be from microseconds to megaseconds, depending on the activity, application, and system. The magnitude of a deadline (how soon it is) is independent of the significance of meeting or missing it some short deadlines are relatively insignificant, and some long deadlines are safety-critical.

Beyond deadlines are more general time constraints e.g., specifying an activity's utility to the system as any function of when it completes. A hard deadline is the special case of a binary unit-valued downward step function, and a soft deadline is the special case of a particular 2-segment linear function. There are also other forms of time constraints. For simplicity and brevity on this page, we will confine our attention to the popular special cases of hard and soft deadlines. Additional information is provided on subsequent pages of this web, beginning with the time constraints page.

Scheduling Optimality Criteria

A system typically includes a multiplicity of actions; at any particular time, some of these actions are ready to execute. In a uniprocessor computer (assumed here for simplicity), only one action can execute at a time, so the action executions need to be sequenced (scheduled or dispatched; the distinction is outside the scope of this page). Usually some sequences of action executions are considered better than others, according to some goal; the goal is formally called the "sequencing optimality criterion".

When the actions have deadlines, the ideal goal is for the system to always meet all of its actions' hard and soft deadlines (the goal normally has other factors also, such as satisfying precedence constraints and resolving resource conflicts, which we disregard here for simplicity). Circumstances may make meeting that goal either not cost-effective, or not possible at all. Frequent examples of such circumstances include: the combination of the actions' deadlines and execution durations; conflicts among the actions for shared resources; the failure of some resources. Given those circumstances, the goal becomes to meet the deadlines as best as possible.

For hard deadlines, "as best as possible" means always meet all the hard deadlines if possible, otherwise change the hard deadline actions in some way to make it possible this is normally done statically by a' priori analysis and scheduling of the actions, or by execution time action admission control.

For soft deadlines, "as best as possible" often means minimize the number of missed soft deadlines or the mean tardiness of the soft deadlines (there are many other possible and popular sequencing goals for soft real-time actions, but we limit ourselves on this page to these two for brevity and simplicity) this may be done either statically a' priori, or dynamically at execution time.

Sequencing goals have two components. The first component is to meet all the hard deadlines, and/or to minimize the number of missed, or the mean tardiness of, the soft deadlines; this is the optimality component of the goal. The second component is how much can be known about that optimality (number of missed deadlines, etc.) before the activities execute; this is the predictability component of the goal.

If the sequencing optimality that will be attained is known exactly, in advance of all the activities completing execution, then the optimality is deterministic this applies both to hard deadlines (it is known in advance that all deadlines will always be met) and soft deadlines (it is known in advance what the number of missed deadlines or the mean tardiness will be). Otherwise, the predictability of the optimality is non-deterministic (usually considered to be stochastic). Deterministic timeliness requires deterministic characteristics of the actions, the system, and the execution environment. Dynamic uncertainties in those characteristics necessitate non-deterministic sequencing optimality.

Predictability is a continuum, with determinism being the maximum predictability end-point. The minimum predictability end-point is that nothing is known a' priori about the optimality which will be attained. (There are various predictability models with analytical measures, but these are outside the scope of this page, and are discussed on a subsequent page.)

System-, application-, and situation-specific acceptable sequencing optimality, and acceptable predictability of that optimality, are essential to the correctness of a system's real-time (i.e., time-constrained) actions. Such timeliness is integral to the logic of the application. This is equally true for actions with hard or soft deadlines. Systems with non-real-time (i.e., non-time-constrained) actions have sequencing goals for those actions (usually focused on system throughput and fairness) with optimality and predictability components but those goals are only for performance rather than for correctness, they are not integral to the logic of the application.

A system having only actions with hard deadlines, and a sequencing goal of always meeting all those hard deadlines (i.e., deterministic maximum sequencing optimality), is a hard real-time system. Many systems have mixtures of hard and soft deadlines, and thus their sequencing goals are that all hard deadlines be met deterministically, and that the number of missed (or tardiness of) the soft deadlines be acceptably low and have acceptably high predictability. Such systems can be said to be hard real-time systems to the degree that they have hard versus soft deadlines.

The theory and techniques employed to guarantee that hard deadlines will always be met are much simpler and more commonly understood than the theory and techniques employed (a' priori or at execution time) to assure that soft deadlines will attain acceptable sequencing optimality and predictability of that optimality. In other words, "Hard real-time is hard, but soft real-time is harder." For this reason, the soft deadlines that are intrinsic to most systems are usually transformed into artificial hard deadlines. This results in the need for increased resources (because the requirement for deterministic characteristics of the activities, system, and environment requires resources to be reserved for the worst cases); consequently, the system is less adaptable to changes.

Friday, July 17, 2009

Creating a shared and static library with the gnu compiler [gcc]

http://www.adp-gmbh.ch/cpp/gcc/create_lib.html

A static library is basically a set of object files that were copied into a single file. This single file is the static library. The static file is created with the archiver (ar).
First, calc_mean.c is turned into an object file:
gcc -c calc_mean.c -o calc_mean.o 
Then, the archiver (ar) is invoked to produce a static library (named libmean.a) out of the object file calc_mean.o.
ar  rcs libmean.a      calc_mean.o 
Note: the library must start with the three letters lib and have the suffix .a.

Creating the shared library

As with static libraries, an object file is created. The -fPIC option tells gcc to create position independant code which is necessary for shared libraries. Note also, that the object file created for the static library will be overwritten. That's not bad, however, because we have a static library that already contains the needed object file.
gcc -c -fPIC calc_mean.c -o calc_mean.o     
For some reason, gcc says:
cc1: warning: -fPIC ignored for target (all code is position independent) 
It looks like -fPIC is not necessary on x86, but all manuals say, it's needed, so I use it too.
Now, the shared library is created
gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1  calc_mean.o 
Note: the library must start with the three letter lib.

The programm using the library

This is the program that uses the calc_mean library. Once, we will link it against the static library and once against the shared library.
main.c
#include <stdio.h> #include "calc_mean.h"  int main(int argc, char* argv[]) {    double v1, v2, m;   v1 = 5.2;   v2 = 7.9;    m  = mean(v1, v2);    printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);    return 0; } 

Linking against static library

gcc -static main.c -L. -lmean -o statically_linked 
Note: the first three letters (the lib) must not be specified, as well as the suffix (.a)

Linking against shared library

gcc main.c -o dynamically_linked -L. -lmean 
Note: the first three letters (the lib) must not be specified, as well as the suffix (.so)

Executing the dynamically linked programm

LD_LIBRARY_PATH=. ./dynamically_linked 

Tuesday, July 14, 2009

Write a Linux Daemon

http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

When a daemon starts up, it has to do some low-level housework to get itself ready for its real job. This involves a few steps:

  • Fork off the parent process
  • Change file mode mask (umask)
  • Open any logs for writing
  • Create a unique Session ID (SID)
  • Change the current working directory to a safe place
  • Close standard file descriptors
  • Enter actual daemon code


Listed below is a complete sample daemon that shows all of the steps necessary for setup and execution. To run this, simply compile using gcc, and start execution from the command line. To terminate, use the kill command after finding its PID.

I've also put in the correct include statements for interfacing with the syslog, which is recommended at the very least for sending start/stop/pause/die log statements, in addition to using your own logs with the fopen()/fwrite()/fclose() function calls.

#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <syslog.h> #include <string.h>  int main(void) {                  /* Our process ID and Session ID */         pid_t pid, sid;                  /* Fork off the parent process */         pid = fork();         if (pid < 0) {                 exit(EXIT_FAILURE);         }         /* If we got a good PID, then            we can exit the parent process. */         if (pid > 0) {                 exit(EXIT_SUCCESS);         }          /* Change the file mode mask */         umask(0);                          /* Open any logs here */                                  /* Create a new SID for the child process */         sid = setsid();         if (sid < 0) {                 /* Log the failure */                 exit(EXIT_FAILURE);         }                            /* Change the current working directory */         if ((chdir("/")) < 0) {                 /* Log the failure */                 exit(EXIT_FAILURE);         }                  /* Close out the standard file descriptors */         close(STDIN_FILENO);         close(STDOUT_FILENO);         close(STDERR_FILENO);                  /* Daemon-specific initialization goes here */                  /* The Big Loop */         while (1) {            /* Do some task here ... */                        sleep(30); /* wait 30 seconds */         }    exit(EXIT_SUCCESS); }   

From here, you can use this skeleton to write your own daemons. Be sure to add in your own logging (or use the syslog facility), and code defensively, code defensively, code defensively!

Wednesday, July 08, 2009

WDS Linked router network

http://www.dd-wrt.com/wiki/index.php/WDS_Linked_router_network

Standard terminology for a two router setup:

  • The client router is the router which does not have an internet connection.
  • The host router is the router which does have the internet connection and is going to share it with other routers.

[edit] Setup

[edit] Two or more WRT54G / WRT54GS / WRT54GL / WTR54GS boxes

  1. (Recommended) Save the current configurations of both routers: Administration -> Backup. Click the Backup button and follow prompts so save NVRAM backup files, i.e. nvram_host.bin, and nvram_client.bin. These configurations can be restored if the new setup doesn't work and you need to quickly revert to the previous (working) configuration.
  2. Reset the client router to its factory default state to eliminate the potential of conflict from other settings. Either use the router's reset button or reset via the GUI: Administration -> Factory Defaults -> Reset router settings -> Restore Factory Defaults - select Yes (radio button), then click Apply Settings button and wait for the router to reboot. (Optional) Unless it is impractical, e.g. the host is part of a working network, reset the host router to its factory default state as well to simplify debugging the new setup.
  3. Change the WAN Connection Type to Disabled on the client router. Setup -> Basic Setup -> WAN Setup -> WAN Connection Type
  4. Set the client router's Local IP Address to one in the same subnet as the host router, i.e. 192.168.1.1 (host/internet gateway) and 192.168.1.2 (client router). If the host router has been reset, set its Local IP Address as well. Set the Gateway and Local DNS IP addresses of the client router to the Local IP Address of the host router. Setup -> Basic Setup -> Network Setup -> Router IP
  5. For the client router, disable the DHCP server (or enable DHCP forwarder) and enter the IP address of the host router as the DHCP server. This allows the host router to perform DHCP services. There can only be one DHCP server on any subnet (network) for reliable operation. Setup -> Basic Setup -> Network Address Server Settings (DHCP)
  6. (Optional) Disable the firewall on the client router. Security -> Firewall -> Firewall Protection -> SPI Firewall
  7. For both host and client routers, set the Wireless Mode to AP and make sure the Wireless Channel is the same. For Wireless Network Mode, select Mixed or G-Only (for WDS to work, B-Only must not be selected). Set the Wireless Network Name (SSID) to your liking. For WPA WDS, the SSID for the routers must be the same; for WEP, or when debugging without security enabled, different SSIDs can make troubleshooting easier. Wireless -> Basic Settings
  8. Disable wireless security on both routers (this should already be done if you reset both routers to factory defaults). Security can be re-enabled after all other steps are complete, but in order to minimize troubleshooting, it's best to get things set up with no security active. If this is impractical, e.g. the host is part of a working network, make certain that all security settings on the client match those of the host exactly. Wireless -> Wireless Security -> Wireless Security wl0
  9. Important: Disable MAC address filtering on the host router (this should already be done if you reset both routers to factory defaults). If this is impractical, e.g. the host is part of a working network, add the wireless MAC address of the client router (see Status -> Sys-Info) to the MAC Filter List of the host router. Wireless -> MAC Filter
  10. Open the WDS configuration page for both routers. For each router, you will see its wireless MAC address (Wireless MAC) at the top of the page. Note that this MAC address is different from the one that may be printed on the case. In the first open row of the table, select LAN from the dropdown list and enter each router's wireless MAC address into the table of the other router. It is not necessary to enable Lazy WDS or WDS Subnet on either router. If necessary, consult WDS - configuration for more than two routers for some helpful info. Wireless -> WDS -> WDS Settings
  11. (Optional) Configure static routing: for Destination LAN NET for the client router enter the IP address of the host router. Use the same settings for Subnet Mask and Gateway that are used by host router. For Interface, select LAN & WLAN. This step ensures that the bridge is given a static IP route. Setup > Advanced Routing -> Static Routing
  12. Check the wireless status page of each router to see that the other is present in the WDS Nodes section. Make sure signal strength for each is not zero. Status -> Wireless -> Wireless Nodes -> WDS Nodes
  13. Test that you can ping the host from the client. Note that it may take a short amount of time for the WDS link to be established, and you may need to reboot either the client or host router (or both).
  14. If disabled, enable wireless security now (highly recommended). If you set the SSID of the client router to be different from that of the host router, you may need to make them the same in order to enable WPA encryption security.

WDS multiple router setup

http://www.dd-wrt.com/wiki/index.php/WDS_multiple_router_setup

Verified with DD-WRT v24-sp2 (06/30/09) build 12424 --Macgyver 22:57, 03 July 2009 (CEST)
This is a 3 router WDS setup using WRT350N and 2 WRT54G, with the 1st WRT54G connecting to the WRT350N, and the 2nd WRT54G connecting to the 1st WRT54G. I have also tested with WRT600N, WRT310N, WRT300N and WRT54GS, so any broadcom-based device should work with these settings
If you only need a 2 router WDS setup, simply ignore the third router setup options; alternately if you need more, just add as needed

Router 1:
WRT350N
Basic setup page:
IP 192.168.1.1
netmask 255.255.255.0
DHCP server enabled

Administration tab:
change TCP timeouts to 120s

Wireless settings:
Make sure all units are using WPA2 Personal AES encryption, same SSID, and wireless channel(s)
(i.e all WPA2 AES, SSID 'ddwrt', channel 6)
on WDS tab set to 'LAN' mode and enter MAC address from first WRT54G
Advanced wireless settings:
Preamble Auto

WRT54G #1
Administration tab:
change TCP timeouts to 120s
change max connections to 1024 if it is set to 512
Services tab:
disable WAN traffic counter and DNS masq

Security tab:
Uncheck 'filter ident' and 'block WAN requests', then disable SPI firewall

Wireless settings:
Wireless mode: G-only
Make sure all units are using WPA2 Personal AES encryption, same SSID, and wireless channel(s)
(i.e all WPA2 AES, SSID 'ddwrt', channel 6)
on WDS tab set to 'LAN' mode and enter MAC address from WRT350N and MAC address from second WRT54G
Advanced wireless settings:
Preamble Auto

Basic setup page:
Connection type: disabled
IP 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1
Assign WAN port to switch checked (optional)
DHCP server disabled
Uncheck all 3 boxes in DHCP section (Use DNSMasq for DHCP/Use DNSMasq for DNS/DHCP-Authoritative)

WRT54G #2
Administration tab:
change TCP timeouts to 120s
change max connections to 1024 if it is set to 512

Services tab:
disable WAN traffic counter and DNS masq

Security tab:
Uncheck 'filter ident' and 'block WAN requests', then disable SPI firewall

Wireless settings:
Wireless mode: G-only
Make sure all units are using WPA2 Personal AES encryption, same SSID, and wireless channel(s)
(i.e all WPA2 AES, SSID 'ddwrt', channel 6)
on WDS tab set to 'LAN' mode and enter MAC address from first WRT54G
Advanced wireless settings:
Preamble Auto

Basic setup page:
Connection type: disabled
IP 192.168.1.3
netmask 255.255.255.0
gateway 192.168.1.1
Assign WAN port to switch checked (optional)
DHCP server disabled
Uncheck all 3 boxes in DHCP section (Use DNSMasq for DHCP/Use DNSMasq for DNS/DHCP-Authoritative)

Reboot first router, then once first router has internet, power up second router, then third, etc...
That's it!

Sunday, July 05, 2009

build multiple languges site with drupal


The following steps are for those who want to have a simple site available in deferent languages. The goal is to have content translated to two or more languages and the visitor to be able to choose any of them. Also, the menus must follow the selection. I have tested the result with content types pageand story. I don't know what happens with forum, for example. I hope this helps you.

In the parentheses I give the relative path in the url. So, if your site ishttp://example.com/drupal and in parentheses I give admin/build/modules, then the url becomes: http://example.com/drupal/admin/build/modules

  1. Install Internationalization module
  2. Go to the modules (admin/build/modules) and in Core - optionalsection enable
    • Locale
    • Content translation
  3. In the Multilanguage - i18n section enable all available. If you haven't enabled Poll and Profile modules, Drupal asks you if you want them enabled. If you don't want them, in the Multilanguage - i18n don't enable Multilanguage Poll and Multilanguage Profile.
  4. Save

You now need the translation files for all the available languages of your site (if you haven't them already). Go to the translations page and download. Then extract them to Drupal's folder (see at 2 minutes 30 seconds into thisvideocast for the correct way to extract translations; you can ignore the rest of the video as it deals with installing Drupal in a language other than English, while this page deals with adding a language after Drupal has already been installed).

You have to add this language:

  1. Go to the Languages page (admin/settings/language)
    • Add all the languages you downloaded and extracted (admin/settings/language/add)
    • Choose Configure
    • In the Language negotiation choose Path prefix only and save settings
  2. Make sure English is the default language
  3. Go to the blocks (admin/build/block)
  4. In the Disabled area choose a Region for the Language switcher
  5. Choose Save blocks

Ok, now you are at a good point. Choosing a language from the Language switcher, the Built-in interface changes to the corresponding language! If it doesn't make sure that it is translated. For that, navigate to admin/build/translate and check the ratio. It must be close to 100%.

The next steps are to make multilingual content.

  1. Enable Multilingual support for all content types you want (admin/content/types)
    • Choose edit for the content type you want (e.g page)
    • In the Workflow settings choose Enabled, with translation and save
  2. Now create content for the content type you have enabled multilingual support (e.g a page) (node/add/page)
  3. In the Language field choose English
  4. Save the page
  5. Choose the Translate link
  6. Choose add translation for the language you want
  7. Write the page. The value in the Language field should show the selected language and be disabled/greyed out.
  8. Save

Now you should be able to switch between translations when viewing the page by using the Language switcher block.

You might want to use flags instead, in which case you'll need the Language Icons module.

For your site to be fully translated you need to have the menus translated. You have two options!

  1. Build a menu for every available language
  2. Build one menu with links that point to every available language. What I mean is that if node/1 is your home page in English and node/2 in Greek, in your menu you have to make a link to node/1 named "Home Page" and one to node/2 named "Αρχική Σελίδα" (this is home page in Greek). You have to do this for every multilingual page.

Try both options and choose what is best for you.

1st option (multiple menus)

  1. Add a new menu (admin/build/menu/add)
  2. In the Menu name give a name, e.g. en-menu
  3. Give title, description and Save
  4. Add an item (admin/build/menu-customize/menu-en-menu/add)
  5. Give the path for the English page (node/1)
  6. Give the English name for the link
  7. In the Language combo box you don't have to choose a language!
  8. Save
  9. Add a new menu for the second language (admin/build/menu/add)
  10. In the Menu name give a name, e.g. el-menu
  11. Add an item (admin/build/menu-customize/menu-el-menu/add)
  12. Give the path (node/2), name and save
  13. Use the same procedure to build menus for all the available languages you have

Ok, you now have your menus. Let's display them.

  1. Go to the blocks (admin/build/block)
  2. Go the the Disabled area and choose a Region for your menus
  3. Choose Save blocks
  4. For your English menu choose configure under Operations column
  5. In the Multilingual settings choose English as language and save
  6. Do the same for the rest menus and choose the appropriate language

2nd option (one menu)

  1. Add a new menu (admin/build/menu/add)
  2. In the Menu name give a name, e.g. multi-menu
  3. Give title, description and Save
  4. Add an item (admin/build/menu-customize/menu-multi-menu/add)
  5. Give the path for the English page (node/1)
  6. Give the English name for the link
  7. In the Language combo box choose English
  8. Save
  9. Add another item (admin/build/menu-customize/menu-el-menu/add)
  10. Give the path (node/2) and name
  11. In the Language combo box choose your language, e.g. Greek
  12. Save
  13. Do the same if node/1 is translated to more languages
  14. Use the same procedure to build menus links for all the available pages you have multilingual

Now, display your menu

  1. Go to the blocks (admin/build/block)
  2. Go the the Disabled area and choose a Region for your menu
  3. Choose Save blocks

Done! Now, when you choose a language on the language switcher, you should see the content translated and the correct menu.