let merge_pot pot po =
  let order_po_map ?(domain) () = 
    match domain with 
      None ->
        po.no_domain :: ( 
          MapTextdomain.fold ( fun _ x lst -> x :: lst ) 
          po.domain []
        )
    | Some domain ->
        let tl = 
          po.no_domain :: (
            MapTextdomain.fold ( 
              fun key x lst -> 
                if key = domain then 
                  lst 
                else 
                  x :: lst 
            ) po.domain []
          )
        in
        try
          (MapTextdomain.find domain po.domain) :: tl
        with Not_found ->
          tl
  in
  let merge_translation map_lst key (location_pot,translation_pot) =
    let translation_merged = 
      try 
        let (_,translation_po) = 
          let map_po = 
            List.find (MapString.mem key) map_lst
          in
          MapString.find key map_po
        in
        (* Implementation of the rule given above *)
        match (translation_pot,translation_po) with
          PoSingular(str_id,_), PoPlural(_, _, str :: _ ) -> 
            PoSingular(str_id, str)
        | PoPlural(str_id, str_plural, _ :: tl ), PoSingular(_, str) ->
            PoPlural(str_id, str_plural, str :: tl)
        | PoPlural(str_id, str_plural, []), PoSingular(_, str) ->
            PoPlural(str_id, str_plural, str :: [])
        | _, translation ->
            translation
      with Not_found ->
        (* Fallback to the translation provided in the POT *)
        translation_pot
    in
    (location_pot,translation_merged)
  in
  (* We begin with an empty po, and merge everything according to the rule 
     above. *)

  let merge_no_domain = 
    MapString.fold ( 
      fun key pot_translation po ->
        add_po_translation_no_domain po 
        (merge_translation (order_po_map ()) key pot_translation)
    ) pot.no_domain empty_po
  in
  let merge_one_domain domain map_domain po = 
    MapString.fold ( 
      fun key pot_translation po ->
        add_po_translation_domain domain po 
        (merge_translation (order_po_map ~domain:domain ()) key pot_translation)
    ) map_domain po
  in
  MapTextdomain.fold merge_one_domain pot.domain merge_no_domain