This answer has superb coverage and links on why different languages can provide distinct benefits to a project. However, there is quite a bit more than just language suitability involved in why projects end up using multiple languages.
Projects end up using multiple languages for six main reasons:
- Cost benefits of reusing code written in other languages;
- The need to include and accommodate legacy code;
- Availability of coders for specific languages;
- The need for special languages for specialty needs;
- Legacy language biases; and
- Poor project management (unplanned multi-language use).
Reasons 1-4 are positive reasons in the sense that addressing them directly can help a project conclude faster, more efficiently, with a higher-quality product, and with easier long-term support. Reasons 5 and 6 are negative, symptoms of resistance to needed change, poor planning, ineffective management, or some combination of all of these factors. These negative factors unfortunately are common causes of "accidental" multi-language use.
Reason 1, the cost benefits of reuse, has become an increasingly powerful reason to allow the use of multiple languages in a project due both to the greater role of open source software and improved capabilities to find the right code components on the web. The "let's code it all internally" philosophy of past decades continues to fade in the face of economic realities, and is essentially never the most cost-effective approach for any new project. This in turn makes opportunities for strict enforcement of the use of a single language within a project less common.
Especially in the case of a project reusing well-managed open source components, the use of multiple languages can provide huge overall cost benefits because the reused components are both hidden behind well-designed interfaces, and are independently maintained by zero-cost external groups. In best-case scenarios, mixing languages via this kind of reuse is no more costly to the project than is using operating system components. I know of no better example of the value of this approach than Microsoft's large-scale adoption of open source software in their browsers.
Reason 2, the need to accommodate legacy code, is ignored at the peril of any large project. However much trouble legacy code may cause, naively assuming that it can be replaced easily with new code in a new language can be incredibly risky. Legacy code, even bad legacy code, often includes what amounts to an implicit "contract" of features expected by the community that uses the legacy product. That community quite often is a major source of revenue for a company, or the main target of support for government software. Simply discarding that implied contract can chase aware customers in droves, and can bankrupt a company overnight if other options are readily available.
At the same time, not replacing old code in an old language can be just as dangerous as replacing it wholesale. A worst-case example is the U.S. Veterans Administration, which has a large number of vital systems coded in a language called MUMPS (no kidding) that was designed by medical doctors, not computer scientists. No one wants to learn MUMPS, and those who do know it are literally dying off. Programmers must therefore accommodate MUMPS even as they try to move forward to using other more common, more powerful, and better-maintained languages.
This type of multi-language use requires careful planning. That planning must navigate the knife edge between losing decades of customer knowledge on one hand, and losing the ability to support the software on the other. Techniques that isolate the old code behind well-defined interfaces, and which enable new more powerful code to replace the old code after its behaviors have been well documented, can help. But this legacy scenario is never easy, and has been (and will continue to be) the cause of the demise of many companies and organizations across a broad spectrum of sizes.
Reason 3, availability of coders for various languages, is a pragmatic factor that projects ignore at their peril. However much the project organizers may feel (correctly or incorrectly) that a particular language is best for their goals, if that language is in conflict with the language expertise pool available to them, both the schedule and quality of the product will suffer from the learning curved of programmers trying to learn a new language.
A more rational approach is to analyze the language needs of the project based on functional areas. For example, looking carefully at the project may show that there is only a small "apex" of high-value code, e.g. for implementing some proprietary algorithm, that requires coding expertise in a some less commonly used language. Other parts of any large project are often easily accommodated by more common languages, or (even better) by well-managed open source products. Analyzing a project by language needs thus can provide a much more realistic and cost-effective approach to hiring or renting special expertise in special languages, and can also help sharpen the interfaces between languages within a single project.
Reason 4, using different languages for different needs, follows immediately and smoothly from performing that kind of analysis of project needs. Care should be used in this also, since selecting too many languages for support within a single project can cause a combinatorial explosion of complexity both in support and interfaces between components. The safest route cost-wise is always to find the maximum opportunities for reuse first, especially if there exist good packages that can meet project needs through little more than customization. Next, some kind of decision should be made on some small number of languages that can address the majority of identified needs. In reuse-intensive development, this will often be a type of glue code.
It is generally not a good idea to choose multiple languages with very similar capabilities just because some members of the project like one and some the other. However, if there are well-identified, well-defined capability subset that would benefit from special language skills, that can be a good reason for using multiple languages for new code development.
Reason 5, resistance to needed changes in the languages used, can be a cause of severe project disruption and internal strife. As user Daveo pointed out in a comment on this answer, change can be very difficult for some project personnel. At the same time, resistance to change is never a simple issue, which is precisely why it can cause much strife. Use of legacy language skills can be a powerful boost to the productivity of a project if the legacy language is sufficiently powerful, and can lead to a product with excellent quality in a team that operates smoothly and respects quality. However, legacy language skills must be balanced with the fact that many older languages can no longer complete with more recent languages in terms of advanced features, component availability, open source options, and intelligent tool kit support.
Both then and now, the single most common (and ironically, most often correct) argument for continuing to use a weaker, less readable, or less productive legacy language has been that the older language enables production of more efficient code. This is an old argument, one that goes all the way back to the 1950s when users of assembly language resented, often bitterly, the emergence of programming in FORTRAN and LISP. An example where even now the code efficiency argument can have validity can be seen in the processing-intensive code such as an operating systems kernel, where C remains the language of choice over C++ (though for reasons that go beyond simple efficiency).
However, in the globally networked and powerfully machine-supported project environments of the new millennium, code efficiency as the main argument for choosing a project language has grown even weaker. The same explosion of computing and networking hardware that has enabled mass marketing of artificial intelligence applications also means that the costs of human programming can easily dwarf those of relativity inefficient code execution on spectacularly cheap hardware and cloudware. When that is combined with the greater availability for in more recent languages of component libraries, open source options, and advanced intelligent tool kits, the number of cases where keeping a language for efficiency reasons alone becomes very narrow. Even in cases where it does apply, the focus should be on using languages such as C that continue to have broad community support.
A more compelling reason for a project to stay with legacy languages occurs when for whatever reasons a project has few or no options for changing its staff. This can happen for example when a major legacy product line is coded entirely in a language with which only the existing staff is fluent. In such cases the project must either continue down the path of trying to program in the old language, or attempt to train existing staff in how to use a new language.
Training legacy language staff in a new language can be a danger all by itself. I still recall a case where a member of a project that had just been trained and transitioned from C to C++ complained to me in all sincerity that he just did not understand the advantages of object-oriented methods. When I looked at his code, he had converted his earlier 103 C functions into 103 methods for a single C++ object class... and rightfully did not see how that helped anything.
The deeper message is that when people have programmed in a single language and language style for years or decades, the difficulty in getting them to "think" in new ways can become almost insurmountable, even with good training programs. In some cases may be no other option but to bring in younger designers and programmers who are more in tune with current trends and methods.
Reason 6, poor project management, speaks for itself. Language selection and use in a project should always be considered and assessed explicitly, and not allowed to happen just by accident. At the very least, language selection can make a huge difference in the long-term fate and support costs of a project, and so should always be taken into account and planned out. Don't become a MUMPS!